Initial client-side-windows work
authorAlexander Larsson <alexl@redhat.com>
Fri, 18 Jul 2008 13:03:42 +0000 (15:03 +0200)
committerAlexander Larsson <alex@localhost.localdomain>
Thu, 2 Apr 2009 08:14:01 +0000 (10:14 +0200)
The history before this was kind of twisted as several different
approaches were tested, so that was all squashed into this initial
commit to hide the uninteresting changes and files that were later
removed.

33 files changed:
gdk/Makefile.am
gdk/gdk.symbols
gdk/gdkcairo.c
gdk/gdkdisplay.c
gdk/gdkdisplay.h
gdk/gdkdraw.c
gdk/gdkdrawable.h
gdk/gdkevents.c
gdk/gdkevents.h
gdk/gdkgc.c
gdk/gdkinternals.h
gdk/gdkoffscreenwindow.c [new file with mode: 0644]
gdk/gdkpango.c
gdk/gdkpixmap.c
gdk/gdkwindow.c
gdk/gdkwindow.h
gdk/gdkwindowimpl.h
gdk/quartz/gdkpixmap-quartz.c
gdk/x11/gdkdisplay-x11.c
gdk/x11/gdkdisplay-x11.h
gdk/x11/gdkdnd-x11.c
gdk/x11/gdkdrawable-x11.c
gdk/x11/gdkevents-x11.c
gdk/x11/gdkgc-x11.c
gdk/x11/gdkgeometry-x11.c
gdk/x11/gdkinput.c
gdk/x11/gdkmain-x11.c
gdk/x11/gdkpixmap-x11.c
gdk/x11/gdkprivate-x11.h
gdk/x11/gdkproperty-x11.c
gdk/x11/gdkselection-x11.c
gdk/x11/gdkwindow-x11.c
gdk/x11/gdkwindow-x11.h

index cc0ae0da04360a24843e0e8dfd6950b245fcd8c1..580db1bdbdb12396368f43e34364174b053fd083 100644 (file)
@@ -120,6 +120,7 @@ gdk_c_sources =                 \
        gdkintl.h               \
        gdkkeys.c               \
        gdkkeyuni.c             \
+       gdkoffscreenwindow.c    \
        gdkpango.c              \
        gdkpixbuf-drawable.c    \
        gdkpixbuf-render.c      \
index cfb54c202368b824f32cc21ee9f88efd5f8077ca..30c5376f1881ac1cc126f921f3b8e935cdc7c206 100644 (file)
@@ -71,7 +71,6 @@ gdk_set_use_xshm
 gdk_keyboard_grab
 gdk_keyboard_grab_info_libgtk_only
 gdk_pointer_grab
-gdk_pointer_grab_info_libgtk_only
 #endif
 #endif
 
@@ -85,6 +84,8 @@ gdk_pointer_is_grabbed
 gdk_pointer_ungrab
 gdk_event_send_client_message
 gdk_event_send_clientmessage_toall
+gdk_pointer_grab_info_libgtk_only
+gdk_display_pointer_is_grabbed
 #endif
 #endif
 
@@ -254,12 +255,6 @@ gdk_visual_type_get_type G_GNUC_CONST
 #endif
 #endif
 
-#if IN_HEADER(__GDK_PIXMAP_H__)
-#if IN_FILE(__GDK_PIXMAP_X11_C__)
-gdk_bitmap_create_from_data
-#endif
-#endif
-
 #if IN_HEADER(__GDK_FONT_H__)
 #if IN_FILE(__GDK_FONT_C__)
 #ifndef GDK_DISABLE_DEPRECATED
@@ -466,7 +461,6 @@ gdk_display_get_default_screen
 gdk_display_get_name
 gdk_display_get_n_screens
 gdk_display_get_screen
-gdk_display_pointer_is_grabbed
 gdk_display_pointer_ungrab
 gdk_display_keyboard_ungrab
 gdk_display_open
@@ -719,6 +713,13 @@ gdk_window_set_composited
 #endif
 #endif
 
+#if IN_HEADER(__GDK_WINDOW_H__)
+#if IN_FILE(__GDK_OFFSCREEN_WINDOW_C__)
+gdk_window_set_offscreen_hooks
+gdk_window_get_offscreen_pixmap
+#endif
+#endif
+
 #if IN_HEADER(__GDK_WINDOW_H__)
 #if IN_FILE(__GDK_DND_X11_C__)
 gdk_window_register_dnd
@@ -925,23 +926,24 @@ gdk_pixbuf_render_to_drawable_alpha
 
 #if IN_HEADER(__GDK_PIXMAP_H__)
 #if IN_FILE(__GDK_PIXMAP_C__)
+gdk_bitmap_create_from_data
 gdk_pixmap_colormap_create_from_xpm
+gdk_pixmap_create_from_data
 gdk_pixmap_create_from_xpm
 gdk_pixmap_colormap_create_from_xpm_d
 gdk_pixmap_create_from_xpm_d
 gdk_pixmap_get_type G_GNUC_CONST
+gdk_pixmap_new
 #endif
 #endif
 
 #if IN_HEADER(__GDK_PIXMAP_H__)
 #if IN_FILE(__GDK_PIXMAP_X11_C__)
-gdk_pixmap_create_from_data
 gdk_pixmap_foreign_new
 gdk_pixmap_foreign_new_for_display
 gdk_pixmap_foreign_new_for_screen
 gdk_pixmap_lookup
 gdk_pixmap_lookup_for_display
-gdk_pixmap_new
 #endif
 #endif
 
index 6e83f53a375f30c8786fc59cbbc67077cf104cb3..9d3ce2d6491407830ab332738b8a7d96f100951e 100644 (file)
@@ -50,6 +50,10 @@ gdk_cairo_create (GdkDrawable *drawable)
 
   surface = _gdk_drawable_ref_cairo_surface (drawable);
   cr = cairo_create (surface);
+
+  if (GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_clip)
+    GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_clip (drawable, cr);
+    
   cairo_surface_destroy (surface);
 
   return cr;
index 9417c4e9475b2bb7d6846fbd2db72e59b3cd3350..1e0c45a0feeba5463099bbb3ed4ff29b3574e5ad 100644 (file)
  */
 
 #include "config.h"
+#include <math.h>
 #include <glib.h>
 #include "gdk.h"               /* gdk_event_send_client_message() */
 #include "gdkdisplay.h"
+#include "gdkwindowimpl.h"
 #include "gdkinternals.h"
 #include "gdkmarshalers.h"
 #include "gdkscreen.h"
@@ -60,6 +62,14 @@ static GdkWindow* singlehead_default_window_get_pointer (GdkWindow       *window
 static GdkWindow* singlehead_default_window_at_pointer  (GdkScreen       *screen,
                                                         gint            *win_x,
                                                         gint            *win_y);
+static GdkWindow *gdk_window_real_window_get_pointer     (GdkDisplay       *display,
+                                                          GdkWindow        *window,
+                                                          gint             *x,
+                                                          gint             *y,
+                                                          GdkModifierType  *mask);
+static GdkWindow *gdk_display_real_get_window_at_pointer (GdkDisplay       *display,
+                                                          gint             *win_x,
+                                                          gint             *win_y);
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
@@ -67,8 +77,8 @@ static char *gdk_sm_client_id;
 
 static const GdkDisplayPointerHooks default_pointer_hooks = {
   _gdk_windowing_get_pointer,
-  _gdk_windowing_window_get_pointer,
-  _gdk_windowing_window_at_pointer
+  gdk_window_real_window_get_pointer,
+  gdk_display_real_get_window_at_pointer
 };
 
 static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
@@ -473,6 +483,79 @@ gdk_display_get_pointer (GdkDisplay      *display,
     *mask = tmp_mask;
 }
 
+static GdkWindow *
+gdk_display_real_get_window_at_pointer (GdkDisplay *display,
+                                        gint       *win_x,
+                                        gint       *win_y)
+{
+  GdkWindow *window;
+  gint x, y;
+
+  window = _gdk_windowing_window_at_pointer (display, &x, &y);
+
+  /* This might need corrections, as the native window returned
+     may contain client side children */
+  if (window)
+    {
+      double xx, yy;
+      
+      window = _gdk_window_find_descendant_at (window,
+                                              x, y, 
+                                              &xx, &yy);
+      x = floor (xx + 0.5);
+      y = floor (yy + 0.5);
+    }
+  
+  *win_x = x;
+  *win_y = y;
+  
+  return window;
+}
+
+static GdkWindow *
+gdk_window_real_window_get_pointer (GdkDisplay       *display,
+                                    GdkWindow        *window,
+                                    gint             *x,
+                                    gint             *y,
+                                    GdkModifierType  *mask)
+{
+  GdkWindowObject *private;
+  GdkWindow *pointer_window;
+  gint tmpx, tmpy;
+
+  private = (GdkWindowObject *) window;
+
+  pointer_window = _gdk_windowing_window_get_pointer (display,
+                                                      window,
+                                                      &tmpx, &tmpy,
+                                                      mask);
+  /* We got the coords on the impl, conver to the window */
+  tmpx += private->abs_x;
+  tmpy += private->abs_y;
+  
+  if (x)
+    *x = tmpx;
+  if (y)
+    *y = tmpy;
+
+  /* We need to recalculate the true child window with the pointer in it
+     due to possible client side child windows */
+  if (pointer_window != NULL)
+    {
+      /* First get the pointer coords relative to pointer_window */
+      _gdk_windowing_window_get_pointer (display,
+                                        pointer_window,
+                                        &tmpx, &tmpy,
+                                        NULL);
+      /* Then convert that to a client side window */
+      pointer_window = _gdk_window_find_descendant_at (pointer_window,
+                                                      tmpx, tmpy, 
+                                                      NULL, NULL);
+    }
+
+  return pointer_window;
+}
+
 /**
  * gdk_display_get_window_at_pointer:
  * @display: a #GdkDisplay
@@ -586,8 +669,8 @@ singlehead_default_window_get_pointer (GdkWindow       *window,
                                       gint            *y,
                                       GdkModifierType *mask)
 {
-  return _gdk_windowing_window_get_pointer (gdk_drawable_get_display (window),
-                                           window, x, y, mask);
+  return gdk_window_real_window_get_pointer (gdk_drawable_get_display (window),
+                                             window, x, y, mask);
 }
 
 static GdkWindow*
@@ -595,8 +678,8 @@ singlehead_default_window_at_pointer  (GdkScreen       *screen,
                                       gint            *win_x,
                                       gint            *win_y)
 {
-  return _gdk_windowing_window_at_pointer (gdk_screen_get_display (screen),
-                                          win_x, win_y);
+  return gdk_display_real_get_window_at_pointer (gdk_screen_get_display (screen),
+                                                 win_x, win_y);
 }
 
 /**
@@ -632,5 +715,200 @@ gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
   return (GdkPointerHooks *)result;
 }
 
+static void
+generate_grab_broken_event (GdkWindow *window,
+                           gboolean   keyboard,
+                           gboolean   implicit,
+                           GdkWindow *grab_window)
+{
+  g_return_if_fail (window != NULL);
+
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      GdkEvent event;
+      event.type = GDK_GRAB_BROKEN;
+      event.grab_broken.window = window;
+      event.grab_broken.send_event = 0;
+      event.grab_broken.keyboard = keyboard;
+      event.grab_broken.implicit = implicit;
+      event.grab_broken.grab_window = grab_window;
+      gdk_event_put (&event);
+    }
+}
+
+void
+_gdk_display_set_has_pointer_grab (GdkDisplay *display,
+                                  GdkWindow *window,
+                                  GdkWindow *native_window,
+                                  gboolean owner_events,
+                                  GdkEventMask event_mask,
+                                  unsigned long serial,
+                                  guint32 time,
+                                  gboolean implicit)
+{
+  int wx, wy;
+  
+  /* Normal GRAB events are sent by listening for enter and leave
+   * events on the native event window, which is then proxied
+   * into the virtual windows when the events are seen.
+   * However, there are two cases where X will not send these events:
+   * * When there is already a grab on the native parent of the
+   *   virtual grab window
+   * * When there is no grab, but the pointer is already in the
+   *   native parent of the virtual grab window
+   * In the first case we send the right GRAB events from the grab, but
+   * in the second case we need to generate our own UNGRAB crossing events.
+   */
+  if (display->pointer_grab.window != NULL &&
+      display->pointer_grab.window != window)
+    {
+      generate_grab_broken_event (GDK_WINDOW (display->pointer_grab.window),
+                                 FALSE, display->pointer_grab.implicit,
+                                 window);
+
+      /* Re-grabbing. Pretend we have no grab for now so that
+        the GRAB events get delivered */
+      display->pointer_grab.window = NULL;
+      _gdk_syntesize_crossing_events (display, 
+                                     display->pointer_grab.window,
+                                     window,
+                                     GDK_CROSSING_GRAB,
+                                     /* These may be stale... */
+                                     display->pointer_info.toplevel_x,
+                                     display->pointer_info.toplevel_y,
+                                     display->pointer_info.state,
+                                     time, TRUE, TRUE);
+    }
+  else if (_gdk_windowing_window_at_pointer (display, &wx, &wy) == native_window)
+    {
+      _gdk_syntesize_crossing_events (display, 
+                                     display->pointer_info.window_under_pointer,
+                                     window,
+                                     GDK_CROSSING_GRAB,
+                                     /* These may be stale... */
+                                     display->pointer_info.toplevel_x,
+                                     display->pointer_info.toplevel_y,
+                                     display->pointer_info.state,
+                                     time, TRUE, TRUE);
+      
+    }
+
+  display->pointer_grab.window = window;
+  display->pointer_grab.native_window = native_window;
+  display->pointer_grab.serial = serial;
+  display->pointer_grab.owner_events = owner_events;
+  display->pointer_grab.event_mask = event_mask;
+  display->pointer_grab.time = time;
+  display->pointer_grab.implicit = implicit;
+  display->pointer_grab.converted_implicit = FALSE;
+}
+
+void
+_gdk_display_unset_has_pointer_grab (GdkDisplay *display,
+                                    gboolean implicit,
+                                    gboolean do_grab_one_pointer_release_event,
+                                    guint32 time)
+{
+  int wx, wy;
+  GdkWindow *old_grab_window;
+  GdkWindow *old_native_grab_window;
+
+
+  old_grab_window = display->pointer_grab.window;
+  old_native_grab_window = display->pointer_grab.native_window;
+
+  if (do_grab_one_pointer_release_event)
+    display->pointer_grab.grab_one_pointer_release_event = display->pointer_grab.window;
+
+  /* We need to set this to null befor syntesizing events to make sure they get
+     delivered to anything but the grab window */
+  display->pointer_grab.window = NULL;
+  
+  /* Normal UNGRAB events are sent by listening for enter and leave
+   * events on the native event window, which is then proxied
+   * into the virtual windows when the events are seen.
+   * However, there are two cases where X will not send these events:
+   * * When this ungrab is due to a new grab on the native window that
+   *   is a parent of the currently grabbed virtual window
+   * * When there is no new grab, and the pointer is already in the
+   *   grabbed virtual windows parent native window
+   * In the first case we send the right GRAB events from the grab, but
+   * in the second case we need to generate our own UNGRAB crossing events.
+   */
+
+  if (_gdk_windowing_window_at_pointer (display, &wx, &wy) == old_native_grab_window)
+    {
+      _gdk_syntesize_crossing_events (display, 
+                                     old_grab_window,
+                                     display->pointer_info.window_under_pointer,
+                                     GDK_CROSSING_UNGRAB,
+                                     /* These may be stale... */
+                                     display->pointer_info.toplevel_x,
+                                     display->pointer_info.toplevel_y,
+                                     display->pointer_info.state,
+                                     time, TRUE, TRUE);
+    }
+  
+  if (implicit)
+    generate_grab_broken_event (old_grab_window,
+                               FALSE, implicit, 
+                               NULL);
+  
+}
+
+
+/**
+ * gdk_pointer_grab_info_libgtk_only:
+ * @display: the #GdkDisplay for which to get the grab information
+ * @grab_window: location to store current grab window
+ * @owner_events: location to store boolean indicating whether
+ *   the @owner_events flag to gdk_pointer_grab() was %TRUE.
+ * 
+ * Determines information about the current pointer grab.
+ * This is not public API and must not be used by applications.
+ * 
+ * Return value: %TRUE if this application currently has the
+ *  pointer grabbed.
+ **/
+gboolean
+gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
+                                  GdkWindow **grab_window,
+                                  gboolean   *owner_events)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  if (display->pointer_grab.window)
+    {
+      if (grab_window)
+        *grab_window = (GdkWindow *)display->pointer_grab.window;
+      if (owner_events)
+        *owner_events = display->pointer_grab.owner_events;
+
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+
+/**
+ * gdk_display_pointer_is_grabbed:
+ * @display: a #GdkDisplay
+ *
+ * Test if the pointer is grabbed.
+ *
+ * Returns: %TRUE if an active X pointer grab is in effect
+ *
+ * Since: 2.2
+ */
+gboolean
+gdk_display_pointer_is_grabbed (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
+  
+  return (display->pointer_grab.window != NULL &&
+         !display->pointer_grab.implicit);
+}
+
 #define __GDK_DISPLAY_C__
 #include "gdkaliasdef.c"
index 04bf1831bbfc48c817d705989f2ee0fa3b031fc3..790bc0b7f3639aecb235ce7678a07a50605a0870 100644 (file)
@@ -43,6 +43,32 @@ typedef struct _GdkDisplayPointerHooks GdkDisplayPointerHooks;
 #define GDK_IS_DISPLAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DISPLAY))
 #define GDK_DISPLAY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DISPLAY, GdkDisplayClass))
 
+/* Tracks information about the pointer grab on this display */
+typedef struct
+{
+  GdkWindow *window;
+  GdkWindow *native_window;
+  gulong serial;
+  gboolean owner_events;
+  guint event_mask;
+  gboolean implicit;
+  gboolean converted_implicit;
+  guint32 time;
+
+  GdkWindow *grab_one_pointer_release_event;
+} GdkPointerGrabInfo;
+
+/* Tracks information about which window the pointer is in and
+ * at what position the mouse is. This is useful when we need
+ * to synthesize events later.
+ */
+typedef struct
+{
+  GdkWindow *window_under_pointer;
+  gdouble toplevel_x, toplevel_y;
+  guint32 state;
+} GdkPointerWindowInfo;
+
 struct _GdkDisplay
 {
   GObject parent_instance;
@@ -68,6 +94,9 @@ struct _GdkDisplay
   guint double_click_distance; /* Maximum distance between clicks in pixels */
   gint button_x[2];             /* The last 2 button click positions. */
   gint button_y[2];
+
+  GdkPointerGrabInfo pointer_grab;
+  GdkPointerWindowInfo pointer_info;
 };
 
 struct _GdkDisplayClass
index 81e6e08390a500a25b160d74f730669e1d2b4f69..7b3fb5a289905491134f14e9e52faad5a3043e50 100644 (file)
@@ -652,6 +652,8 @@ gdk_draw_drawable (GdkDrawable *drawable,
                                                           &composite_x_offset,
                                                           &composite_y_offset);
 
+  /* TODO: For non-native windows this may copy stuff from other overlapping
+     windows. We should clip that and clear that area in the destination instead. */
   
   GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, composite,
                                                     xsrc - composite_x_offset,
@@ -871,7 +873,7 @@ real_draw_glyphs (GdkDrawable       *drawable,
   cairo_t *cr;
 
   cr = gdk_cairo_create (drawable);
-  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE);
+  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
 
   if (matrix)
     {
@@ -995,7 +997,7 @@ gdk_draw_trapezoids (GdkDrawable        *drawable,
   g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL);
 
   cr = gdk_cairo_create (drawable);
-  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE);
+  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
   
   for (i = 0; i < n_trapezoids; i++)
     {
@@ -1185,7 +1187,7 @@ gdk_drawable_real_get_image (GdkDrawable     *drawable,
   return gdk_drawable_copy_to_image (drawable, NULL, x, y, 0, 0, width, height);
 }
 
-static GdkDrawable*
+static GdkDrawable *
 gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
                                           gint         x,
                                           gint         y,
@@ -1771,5 +1773,25 @@ _gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
     }
 }
 
+/**
+ * _gdk_drawable_get_source_drawable:
+ * @drawable: a #GdkDrawable
+ *
+ * Returns a drawable for the passed @drawable that is guaranteed to be
+ * usable to create a pixmap (e.g.: not an offscreen window).
+ *
+ * Since: 2.16
+ */
+GdkDrawable *
+_gdk_drawable_get_source_drawable (GdkDrawable *drawable)
+{
+  g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
+
+  if (GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable)
+    return GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable (drawable);
+
+  return drawable;
+}
+
 #define __GDK_DRAW_C__
 #include "gdkaliasdef.c"
index 508bf86fcfd2027816c687c524dd2c471a566dd1..10910c0c244e90975d75898b359fea735b6cf326 100644 (file)
@@ -200,9 +200,11 @@ struct _GdkDrawableClass
 
   cairo_surface_t *(*ref_cairo_surface) (GdkDrawable *drawable);
 
+  GdkDrawable *(*get_source_drawable) (GdkDrawable *drawable);
+
+  void         (*set_cairo_clip)      (GdkDrawable *drawable,
+                                      cairo_t *cr);
   /* Padding for future expansion */
-  void         (*_gdk_reserved4)  (void);
-  void         (*_gdk_reserved5)  (void);
   void         (*_gdk_reserved6)  (void);
   void         (*_gdk_reserved7)  (void);
   void         (*_gdk_reserved9)  (void);
index 24a29a1fd96e8b560f380ed4175e7cae3cf2707b..0071401532d0634675bae00f92a83ec214754551 100644 (file)
@@ -120,6 +120,63 @@ _gdk_event_queue_append (GdkDisplay *display,
   return display->queued_tail;
 }
 
+/**
+ * _gdk_event_queue_insert_after:
+ * @display: a #GdkDisplay
+ * @sibling: Append after this event.
+ * @event: Event to append.
+ *
+ * Appends an event after the specified event, or if it isn't in
+ * the queue, onto the tail of the event queue.
+ *
+ * Returns: the newly appended list node.
+ *
+ * Since: 2.16
+ */
+GList*
+_gdk_event_queue_insert_after (GdkDisplay *display,
+                               GdkEvent   *sibling,
+                               GdkEvent   *event)
+{
+  GList *prev = g_list_find (display->queued_events, sibling);
+  if (prev && prev->next)
+    {
+      display->queued_events = g_list_insert_before (display->queued_events, prev->next, event);
+      return prev->next;
+    }
+  else
+    return _gdk_event_queue_append (display, event);
+}
+
+/**
+ * _gdk_event_queue_insert_after:
+ * @display: a #GdkDisplay
+ * @sibling: Append after this event.
+ * @event: Event to append.
+ *
+ * Appends an event before the specified event, or if it isn't in
+ * the queue, onto the tail of the event queue.
+ *
+ * Returns: the newly appended list node.
+ *
+ * Since: 2.16
+ */
+GList*
+_gdk_event_queue_insert_before (GdkDisplay *display,
+                               GdkEvent   *sibling,
+                               GdkEvent   *event)
+{
+  GList *next = g_list_find (display->queued_events, sibling);
+  if (next)
+    {
+      display->queued_events = g_list_insert_before (display->queued_events, next, event);
+      return next->prev;
+    }
+  else
+    return _gdk_event_queue_append (display, event);
+}
+
+
 /**
  * _gdk_event_queue_remove_link:
  * @display: a #GdkDisplay
@@ -1101,13 +1158,16 @@ gdk_synthesize_click (GdkDisplay *display,
                      gint        nclicks)
 {
   GdkEvent temp_event;
+  GdkEvent *event_copy;
+  GList *link;
   
   g_return_if_fail (event != NULL);
   
   temp_event = *event;
   temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
-  
-  gdk_display_put_event (display, &temp_event);
+
+  event_copy = gdk_event_copy (&temp_event);
+  link = _gdk_event_queue_append (display, event_copy);
 }
 
 void
index e64acb7b9f7f2a631d9d18476a2df364a99d75ad..5d8e28915ba71d5f45a832f9b0ade0a8ab90b912 100644 (file)
@@ -151,7 +151,8 @@ typedef enum
   GDK_SETTING           = 33,
   GDK_OWNER_CHANGE      = 34,
   GDK_GRAB_BROKEN       = 35,
-  GDK_DAMAGE            = 36
+  GDK_DAMAGE            = 36,
+  GDK_EVENT_LAST        /* helper variable for decls */
 } GdkEventType;
 
 /* Event masks. (Used to select what types of events a window
index f3389c70eaef2a855ba00615a7efd0b6eb0bd787..7b7e4eed5915645c9558985776e98011ce23423c 100644 (file)
@@ -43,6 +43,8 @@ struct _GdkGCPrivate
 {
   GdkRegion *clip_region;
 
+  GdkSubwindowMode subwindow_mode;
+  
   GdkFill fill;
   GdkBitmap *stipple;
   GdkPixmap *tile;
@@ -172,6 +174,8 @@ _gdk_gc_init (GdkGC           *gc,
     priv->fg_pixel = values->foreground.pixel;
   if (values_mask & GDK_GC_BACKGROUND)
     priv->bg_pixel = values->background.pixel;
+  if (values_mask & GDK_GC_SUBWINDOW)
+    priv->subwindow_mode = values->subwindow_mode;
 
   gc->colormap = gdk_drawable_get_colormap (drawable);
   if (gc->colormap)
@@ -183,7 +187,7 @@ gdk_gc_finalize (GObject *object)
 {
   GdkGC *gc = GDK_GC (object);
   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
-  
+
   if (priv->clip_region)
     gdk_region_destroy (priv->clip_region);
   if (gc->colormap)
@@ -313,6 +317,8 @@ gdk_gc_set_values (GdkGC           *gc,
     priv->fg_pixel = values->foreground.pixel;
   if (values_mask & GDK_GC_BACKGROUND)
     priv->bg_pixel = values->background.pixel;
+  if (values_mask & GDK_GC_SUBWINDOW)
+    priv->subwindow_mode = values->subwindow_mode;
   
   GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask);
 }
@@ -542,9 +548,11 @@ gdk_gc_set_clip_mask (GdkGC        *gc,
   gdk_gc_set_values (gc, &values, GDK_GC_CLIP_MASK);
 }
 
-static void
+/* Takes ownership of passed in region */
+void
 _gdk_gc_set_clip_region_internal (GdkGC     *gc,
-                                 GdkRegion *region)
+                                 GdkRegion *region,
+                                 gboolean reset_origin)
 {
   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
 
@@ -553,7 +561,32 @@ _gdk_gc_set_clip_region_internal (GdkGC     *gc,
 
   priv->clip_region = region;
 
-  _gdk_windowing_gc_set_clip_region (gc, region);
+  _gdk_windowing_gc_set_clip_region (gc, region, reset_origin);
+}
+
+/* Takes ownership of passed in region, returns old clip region */
+void
+_gdk_gc_intersect_clip_region (GdkGC     *gc,
+                              GdkRegion *region,
+                              GdkRegion **old_clip_region)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+  GdkRegion *old_clip;
+
+  old_clip = priv->clip_region;
+
+  priv->clip_region = region;
+  if (old_clip)
+    gdk_region_intersect (region, old_clip);
+
+  if (old_clip_region)
+    *old_clip_region = old_clip;
+  else
+    gdk_region_destroy (old_clip);
+  
+  _gdk_windowing_gc_set_clip_region (gc, priv->clip_region, FALSE);
+  
+  return old_clip;
 }
 
 /**
@@ -578,7 +611,7 @@ gdk_gc_set_clip_rectangle (GdkGC              *gc,
   else
     region = NULL;
 
-  _gdk_gc_set_clip_region_internal (gc, region);
+  _gdk_gc_set_clip_region_internal (gc, region, TRUE);
 }
 
 /**
@@ -603,7 +636,7 @@ gdk_gc_set_clip_region (GdkGC           *gc,
   else
     copy = NULL;
 
-  _gdk_gc_set_clip_region_internal (gc, copy);
+  _gdk_gc_set_clip_region_internal (gc, copy, TRUE);
 }
 
 /**
@@ -723,13 +756,27 @@ gdk_gc_set_subwindow (GdkGC              *gc,
                      GdkSubwindowMode  mode)
 {
   GdkGCValues values;
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
 
   g_return_if_fail (GDK_IS_GC (gc));
 
+  /* This could get called a lot to reset the subwindow mode in
+     the client side clipping, so bail out early */ 
+  if (priv->subwindow_mode == mode)
+    return;
+  
   values.subwindow_mode = mode;
   gdk_gc_set_values (gc, &values, GDK_GC_SUBWINDOW);
 }
 
+GdkSubwindowMode
+_gdk_gc_get_subwindow (GdkGC *gc)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+  return priv->subwindow_mode;
+}
+
 /**
  * gdk_gc_set_exposures:
  * @gc: a #GdkGC.
@@ -907,6 +954,7 @@ gdk_gc_copy (GdkGC *dst_gc,
 
   dst_priv->fg_pixel = src_priv->fg_pixel;
   dst_priv->bg_pixel = src_priv->bg_pixel;
+  dst_priv->subwindow_mode = src_priv->subwindow_mode;
 }
 
 /**
@@ -1117,6 +1165,8 @@ gc_get_background (GdkGC    *gc,
  *   the fill mode will be forced to %GDK_STIPPLED
  * @gc_changed: pass %FALSE if the @gc has not changed since the
  *     last call to this function
+ * @target_drawable: The drawable you're drawing in. If passed in
+ *     this is used for client side window clip emulation.
  * 
  * Set the attributes of a cairo context to match those of a #GdkGC
  * as far as possible. Some aspects of a #GdkGC, such as clip masks
@@ -1127,7 +1177,8 @@ _gdk_gc_update_context (GdkGC          *gc,
                         cairo_t        *cr,
                         const GdkColor *override_foreground,
                         GdkBitmap      *override_stipple,
-                        gboolean        gc_changed)
+                        gboolean        gc_changed,
+                       GdkDrawable    *target_drawable)
 {
   GdkGCPrivate *priv;
   GdkFill fill;
@@ -1246,6 +1297,10 @@ _gdk_gc_update_context (GdkGC          *gc,
 
       cairo_clip (cr);
     }
+
+  /* The reset above resets the window clip rect, so we want to re-set that */
+  if (target_drawable && GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip)
+    GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip (target_drawable, cr);
 }
 
 
index 61a5433e2aade64525ee7cfef3789105878b722e..b8fd252ca2bb1104e8112e313eb3672f5786d4a0 100644 (file)
@@ -182,15 +182,21 @@ extern gchar     *_gdk_display_arg_name;
 void      _gdk_events_queue  (GdkDisplay *display);
 GdkEvent* _gdk_event_unqueue (GdkDisplay *display);
 
-GList* _gdk_event_queue_find_first  (GdkDisplay *display);
-void   _gdk_event_queue_remove_link (GdkDisplay *display,
-                                    GList      *node);
-GList*  _gdk_event_queue_prepend    (GdkDisplay *display,
-                                    GdkEvent   *event);
-GList*  _gdk_event_queue_append     (GdkDisplay *display,
-                                    GdkEvent   *event);
-void _gdk_event_button_generate     (GdkDisplay *display,
-                                    GdkEvent   *event);
+GList* _gdk_event_queue_find_first   (GdkDisplay *display);
+void   _gdk_event_queue_remove_link  (GdkDisplay *display,
+                                     GList      *node);
+GList* _gdk_event_queue_prepend      (GdkDisplay *display,
+                                     GdkEvent   *event);
+GList* _gdk_event_queue_append       (GdkDisplay *display,
+                                     GdkEvent   *event);
+GList* _gdk_event_queue_insert_after (GdkDisplay *display,
+                                      GdkEvent   *after_event,
+                                      GdkEvent   *event);
+GList* _gdk_event_queue_insert_before(GdkDisplay *display,
+                                      GdkEvent   *after_event,
+                                      GdkEvent   *event);
+void   _gdk_event_button_generate    (GdkDisplay *display,
+                                     GdkEvent   *event);
 
 void _gdk_windowing_event_data_copy (const GdkEvent *src,
                                      GdkEvent       *dst);
@@ -227,6 +233,8 @@ GdkImage *_gdk_drawable_copy_to_image (GdkDrawable  *drawable,
 
 cairo_surface_t *_gdk_drawable_ref_cairo_surface (GdkDrawable *drawable);
 
+GdkDrawable *_gdk_drawable_get_source_drawable (GdkDrawable *drawable);
+
 /* GC caching */
 GdkGC *_gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
                                     gboolean     graphics_exposures);
@@ -235,20 +243,41 @@ void _gdk_gc_update_context (GdkGC          *gc,
                             cairo_t        *cr,
                             const GdkColor *override_foreground,
                             GdkBitmap      *override_stipple,
-                            gboolean        gc_changed);
+                            gboolean        gc_changed,
+                            GdkDrawable    *target_drawable);
 
 /*************************************
  * Interfaces used by windowing code *
  *************************************/
 
-GdkWindow *_gdk_window_new               (GdkWindow     *window,
-                                          GdkWindowAttr *attributes,
-                                          gint           attributes_mask);
-void       _gdk_window_destroy           (GdkWindow     *window,
-                                         gboolean       foreign_destroy);
-void       _gdk_window_clear_update_area (GdkWindow     *window);
-
-void       _gdk_screen_close             (GdkScreen     *screen);
+GdkPixmap *_gdk_pixmap_new               (GdkDrawable    *drawable,
+                                          gint            width,
+                                          gint            height,
+                                          gint            depth);
+GdkPixmap *_gdk_pixmap_create_from_data  (GdkDrawable    *drawable,
+                                          const gchar    *data,
+                                          gint            width,
+                                          gint            height,
+                                          gint            depth,
+                                          const GdkColor *fg,
+                                          const GdkColor *bg);
+GdkPixmap *_gdk_bitmap_create_from_data  (GdkDrawable    *drawable,
+                                          const gchar    *data,
+                                          gint            width,
+                                          gint            height);
+
+void       _gdk_window_impl_new          (GdkWindow      *window,
+                                         GdkScreen      *screen,
+                                         GdkVisual      *visual,
+                                         GdkEventMask    event_mask,
+                                          GdkWindowAttr  *attributes,
+                                          gint            attributes_mask);
+void       _gdk_window_destroy           (GdkWindow      *window,
+                                          gboolean        foreign_destroy);
+void       _gdk_window_clear_update_area (GdkWindow      *window);
+void       _gdk_window_update_size       (GdkWindow      *window);
+
+void       _gdk_screen_close             (GdkScreen      *screen);
 
 const char *_gdk_get_sm_client_id (void);
 
@@ -263,6 +292,13 @@ GdkPixmap *_gdk_gc_get_tile        (GdkGC *gc);
 GdkBitmap *_gdk_gc_get_stipple     (GdkGC *gc);
 guint32    _gdk_gc_get_fg_pixel    (GdkGC *gc);
 guint32    _gdk_gc_get_bg_pixel    (GdkGC *gc);
+void      _gdk_gc_intersect_clip_region     (GdkGC     *gc,
+                                            GdkRegion *region,
+                                            GdkRegion **old_region);
+void       _gdk_gc_set_clip_region_internal (GdkGC     *gc,
+                                            GdkRegion *region,
+                                            gboolean reset_origin);
+GdkSubwindowMode _gdk_gc_get_subwindow (GdkGC *gc);
 
 /*****************************************
  * Interfaces provided by windowing code *
@@ -306,21 +342,14 @@ GdkWindow* _gdk_windowing_window_at_pointer  (GdkDisplay       *display,
 gint _gdk_windowing_get_bits_for_depth (GdkDisplay *display,
                                        gint        depth);
 
-void       _gdk_window_reparent                   (GdkWindow     *window,
-                                                  GdkWindow     *new_parent,
-                                                  gint           x,
-                                                  gint           y);
 
 #define GDK_WINDOW_IS_MAPPED(window) ((((GdkWindowObject*)window)->state & GDK_WINDOW_STATE_WITHDRAWN) == 0)
 
-/* Called before processing updates for a window. This gives the windowing
- * layer a chance to save the region for later use in avoiding duplicate
- * exposes. The return value indicates whether the function has a saved
- * the region; if the result is TRUE, then the windowing layer is responsible
- * for destroying the region later.
- */
-gboolean _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
-                                                GdkRegion *area);
+void _gdk_windowing_window_queue_translation (GdkWindow *window,
+                                             GdkRegion *area,
+                                             gint       dx,
+                                             gint       dy);
+
 
 /* Called to do the windowing system specific part of gdk_window_destroy(),
  *
@@ -387,6 +416,7 @@ GType _gdk_pixmap_impl_get_type (void) G_GNUC_CONST;
  * _gdk_windowing_gc_set_clip_region:
  * @gc: a #GdkGC
  * @region: the new clip region
+ * @reset_origin: if TRUE, reset the clip_x/y_origin values to 0
  * 
  * Do any window-system specific processing necessary
  * for a change in clip region. Since the clip origin
@@ -398,7 +428,8 @@ GType _gdk_pixmap_impl_get_type (void) G_GNUC_CONST;
  * will already return the new region.
  **/
 void _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
-                                       const GdkRegion *region);
+                                       const GdkRegion *region,
+                                       gboolean reset_origin);
 
 /**
  * _gdk_windowing_gc_copy:
@@ -435,6 +466,78 @@ char *_gdk_windowing_get_startup_notify_id (GAppLaunchContext *context,
 void  _gdk_windowing_launch_failed         (GAppLaunchContext *context, 
                                            const char        *startup_notify_id);
 
+void _gdk_windowing_grab_broken          (GdkDisplay *display);
+
+void _gdk_display_set_has_pointer_grab (GdkDisplay *display,
+                                       GdkWindow *window,
+                                       GdkWindow *native_window,
+                                       gboolean owner_events,
+                                       GdkEventMask event_mask,
+                                       unsigned long serial,
+                                       guint32 time,
+                                       gboolean implicit);
+void _gdk_display_unset_has_pointer_grab (GdkDisplay *display,
+                                         gboolean implicit,
+                                         gboolean do_grab_one_pointer_release_event,
+                                         guint32 time);
+
+void _gdk_window_invalidate_for_expose (GdkWindow       *window,
+                                       const GdkRegion *region);
+
+void _gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+                                           int width,
+                                           int height);
+
+cairo_surface_t * _gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+                                                      int width,
+                                                      int height);
+GdkWindow * _gdk_window_find_descendant_at (GdkWindow *toplevel,
+                                           double x, double y,
+                                           double *found_x,
+                                           double *found_y);
+
+void _gdk_window_add_damage (GdkWindow *toplevel,
+                            GdkRegion *damaged_region);
+
+GdkEvent * _gdk_make_event (GdkWindow    *window,
+                           GdkEventType  type,
+                           GdkEvent     *event_in_queue,
+                           gboolean      before_event);
+
+void _gdk_syntesize_crossing_events (GdkDisplay                 *display,
+                                    GdkWindow                  *src,
+                                    GdkWindow                  *dest,
+                                    GdkCrossingMode             mode,
+                                    gint                        toplevel_x,
+                                    gint                        toplevel_y,
+                                    GdkModifierType             mask,
+                                    guint32                     time_,
+                                    gboolean                    do_first,
+                                    gboolean                    do_last);
+
+void _gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window);
+
+GdkRegion *_gdk_window_calculate_full_clip_region    (GdkWindow     *window,
+                                                      GdkWindow     *base_window,
+                                                      gboolean       do_children,
+                                                      gint          *base_x_offset,
+                                                      gint          *base_y_offset);
+gboolean    _gdk_window_has_impl (GdkWindow *window);
+GdkWindow * _gdk_window_get_impl_window (GdkWindow *window);
+
+
+/*****************************
+ * offscreen window routines *
+ *****************************/
+GType gdk_offscreen_window_get_type (void);
+void       _gdk_offscreen_window_new                 (GdkWindow     *window,
+                                                     GdkScreen     *screen,
+                                                     GdkVisual     *visual,
+                                                     GdkWindowAttr *attributes,
+                                                     gint           attributes_mask);
+void       _gdk_offscreen_window_destroy             (GdkWindow     *window,
+                                                      gboolean       recursing);
+
 
 /************************************
  * Initialization and exit routines *
diff --git a/gdk/gdkoffscreenwindow.c b/gdk/gdkoffscreenwindow.c
new file mode 100644 (file)
index 0000000..4055c5a
--- /dev/null
@@ -0,0 +1,1217 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2005.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include <config.h>
+#include <math.h>
+#include "gdk.h"
+#include "gdkwindow.h"
+#include "gdkinternals.h"
+#include "gdkwindowimpl.h"
+#include "gdkpixmap.h"
+#include "gdkdrawable.h"
+#include "gdktypes.h"
+#include "gdkscreen.h"
+#include "gdkgc.h"
+#include "gdkcolor.h"
+#include "gdkcursor.h"
+#include "gdkalias.h"
+
+/* LIMITATIONS:
+ *
+ * Offscreen windows can't be the child of a foreign window,
+ *   nor contain foreign windows
+ * GDK_POINTER_MOTION_HINT_MASK isn't effective
+ */
+
+typedef struct _GdkOffscreenWindow      GdkOffscreenWindow;
+typedef struct _GdkOffscreenWindowClass GdkOffscreenWindowClass;
+
+struct _GdkOffscreenWindow
+{
+  GdkDrawable parent_instance;
+
+  GdkWindow *wrapper;
+  GdkCursor *cursor;
+  GdkColormap *colormap;
+  GdkScreen *screen;
+
+  GdkPixmap *pixmap;
+};
+
+struct _GdkOffscreenWindowClass
+{
+  GdkDrawableClass parent_class;
+};
+
+#define GDK_TYPE_OFFSCREEN_WINDOW            (gdk_offscreen_window_get_type())
+#define GDK_OFFSCREEN_WINDOW(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindow))
+#define GDK_IS_OFFSCREEN_WINDOW(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_OFFSCREEN_WINDOW))
+#define GDK_OFFSCREEN_WINDOW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
+#define GDK_IS_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_OFFSCREEN_WINDOW))
+#define GDK_OFFSCREEN_WINDOW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
+
+static void       gdk_offscreen_window_impl_iface_init    (GdkWindowImplIface         *iface);
+static void       gdk_offscreen_window_hide               (GdkWindow                  *window);
+static void       gdk_offscreen_window_clear_area         (GdkWindow                  *window,
+                                                          gint                        x,
+                                                          gint                        y,
+                                                          gint                        width,
+                                                          gint                        height,
+                                                          gboolean                    send_expose);
+
+
+G_DEFINE_TYPE_WITH_CODE (GdkOffscreenWindow,
+                         gdk_offscreen_window,
+                         GDK_TYPE_DRAWABLE,
+                        G_IMPLEMENT_INTERFACE (GDK_TYPE_WINDOW_IMPL,
+                                               gdk_offscreen_window_impl_iface_init));
+
+
+static void
+gdk_offscreen_window_finalize (GObject *object)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (object);
+
+  if (offscreen->cursor)
+    gdk_cursor_unref (offscreen->cursor);
+
+  offscreen->cursor = NULL;
+
+  gdk_pixmap_unref (offscreen->pixmap);
+  
+  G_OBJECT_CLASS (gdk_offscreen_window_parent_class)->finalize (object);
+}
+
+static void
+gdk_offscreen_window_init (GdkOffscreenWindow *window)
+{
+}
+
+void
+_gdk_offscreen_window_destroy (GdkWindow *window,
+                               gboolean   recursing)
+{
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (!recursing)
+    gdk_offscreen_window_hide (window);
+
+  g_object_unref (offscreen->colormap);
+  offscreen->colormap = NULL;
+}
+
+static gboolean
+is_parent_of (GdkWindow *parent,
+              GdkWindow *child)
+{
+  GdkWindow *w;
+
+  w = child;
+  while (w != NULL)
+    {
+      if (w == parent)
+       return TRUE;
+
+      w = gdk_window_get_parent (w);
+    }
+
+  return FALSE;
+}
+
+static GdkGC *
+gdk_offscreen_window_create_gc (GdkDrawable     *drawable,
+                               GdkGCValues     *values,
+                               GdkGCValuesMask  values_mask)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return gdk_gc_new_with_values (offscreen->pixmap, values, values_mask);
+}
+
+static GdkImage*
+gdk_offscreen_window_copy_to_image (GdkDrawable    *drawable,
+                                   GdkImage       *image,
+                                   gint            src_x,
+                                   gint            src_y,
+                                   gint            dest_x,
+                                   gint            dest_y,
+                                   gint            width,
+                                   gint            height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return gdk_drawable_copy_to_image (offscreen->pixmap,
+                                     image,
+                                     src_x,
+                                     src_y,
+                                     dest_x, dest_y,
+                                     width, height);
+}
+
+static cairo_surface_t *
+gdk_offscreen_window_ref_cairo_surface (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  
+  return _gdk_drawable_ref_cairo_surface (offscreen->pixmap);
+}
+
+static GdkColormap*
+gdk_offscreen_window_get_colormap (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return offscreen->colormap;
+}
+
+static void
+gdk_offscreen_window_set_colormap (GdkDrawable *drawable,
+                                  GdkColormap*colormap)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  if (colormap && GDK_WINDOW_DESTROYED (offscreen->wrapper))
+    return;
+
+  if (offscreen->colormap == colormap)
+    return;
+
+  if (offscreen->colormap)
+    g_object_unref (offscreen->colormap);
+
+  offscreen->colormap = colormap;
+  if (offscreen->colormap)
+    g_object_ref (offscreen->colormap);
+}
+
+
+static gint
+gdk_offscreen_window_get_depth (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return gdk_drawable_get_depth (offscreen->wrapper);
+}
+
+static GdkDrawable *
+gdk_offscreen_window_get_source_drawable (GdkDrawable  *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return _gdk_drawable_get_source_drawable (offscreen->pixmap);
+}
+
+static GdkDrawable *
+gdk_offscreen_window_get_composite_drawable (GdkDrawable *drawable,
+                                            gint         x,
+                                            gint         y,
+                                            gint         width,
+                                            gint         height,
+                                            gint        *composite_x_offset,
+                                            gint        *composite_y_offset)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return g_object_ref (offscreen->pixmap);
+}
+
+static GdkScreen*
+gdk_offscreen_window_get_screen (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return offscreen->screen;
+}
+
+static GdkVisual*
+gdk_offscreen_window_get_visual (GdkDrawable    *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return gdk_drawable_get_visual (offscreen->wrapper);
+}
+
+static void
+add_damage (GdkOffscreenWindow *offscreen,
+           int x, int y,
+           int w, int h)
+{
+  GdkRectangle rect;
+  GdkRegion *damage;
+  
+  rect.x = x;
+  rect.y = y;
+  rect.width = w;
+  rect.height = h;
+
+  damage = gdk_region_rectangle (&rect);
+  _gdk_window_add_damage (offscreen->wrapper, damage);
+  gdk_region_destroy (damage);
+}
+
+static void
+gdk_offscreen_window_draw_drawable (GdkDrawable *drawable,
+                                   GdkGC       *gc,
+                                   GdkPixmap   *src,
+                                   gint         xsrc,
+                                   gint         ysrc,
+                                   gint         xdest,
+                                   gint         ydest,
+                                   gint         width,
+                                   gint         height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+  
+  gdk_draw_drawable (real_drawable, gc,
+                    src, xsrc, ysrc,
+                    xdest, ydest,
+                    width, height);
+
+  add_damage (offscreen, xdest, ydest, width, height);
+}
+
+static void
+gdk_offscreen_window_draw_rectangle (GdkDrawable  *drawable,
+                                    GdkGC        *gc,
+                                    gboolean      filled,
+                                    gint          x,
+                                    gint          y,
+                                    gint          width,
+                                    gint          height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+  gdk_draw_rectangle (real_drawable,
+                     gc, filled, x, y, width, height);
+
+  add_damage (offscreen, x, y, width, height);
+  
+}
+
+static void
+gdk_offscreen_window_draw_arc (GdkDrawable  *drawable,
+                              GdkGC           *gc,
+                              gboolean filled,
+                              gint             x,
+                              gint             y,
+                              gint             width,
+                              gint             height,
+                              gint             angle1,
+                              gint             angle2)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+  gdk_draw_arc (real_drawable,
+               gc,
+               filled,
+               x,
+               y,
+               width,
+               height,
+               angle1,
+               angle2);
+  add_damage (offscreen, x, y, width, height);
+}
+
+static void
+gdk_offscreen_window_draw_polygon (GdkDrawable  *drawable,
+                                  GdkGC               *gc,
+                                  gboolean     filled,
+                                  GdkPoint     *points,
+                                  gint         npoints)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+  
+  gdk_draw_polygon (real_drawable,
+                   gc,
+                   filled,
+                   points,
+                   npoints);
+
+  if (npoints > 0)
+    {
+      int min_x, min_y, max_x, max_y, i;
+      
+      min_x = max_x = points[0].x;
+      min_y = max_y = points[0].y;
+      
+       for (i = 1; i < npoints; i++)
+         {
+           min_x = MIN (min_x, points[i].x);
+           max_x = MAX (max_x, points[i].x);
+           min_y = MIN (min_y, points[i].y);
+           max_y = MAX (max_y, points[i].y);
+         }
+       
+       add_damage (offscreen, min_x, min_y,
+                   max_x - min_x,
+                   max_y - min_y);
+    }
+}
+
+static void
+gdk_offscreen_window_draw_text (GdkDrawable  *drawable,
+                               GdkFont      *font,
+                               GdkGC          *gc,
+                               gint            x,
+                               gint            y,
+                               const gchar  *text,
+                               gint            text_length)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+  gdk_draw_text (real_drawable,
+                font,
+                gc,
+                x,
+                y,
+                text,
+                text_length);
+
+  /* Hard to compute the minimal size, not that often used anyway. */
+  add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_text_wc (GdkDrawable  *drawable,
+                                  GdkFont       *font,
+                                  GdkGC                 *gc,
+                                  gint           x,
+                                  gint           y,
+                                  const GdkWChar *text,
+                                  gint           text_length)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+  gdk_draw_text_wc (real_drawable,
+                   font,
+                   gc,
+                   x,
+                   y,
+                   text,
+                   text_length);
+
+  /* Hard to compute the minimal size, not that often used anyway. */
+  add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_points (GdkDrawable  *drawable,
+                                 GdkGC        *gc,
+                                 GdkPoint     *points,
+                                 gint          npoints)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+  gdk_draw_points (real_drawable,
+                  gc,
+                  points,
+                  npoints);
+
+
+  if (npoints > 0)
+    {
+      int min_x, min_y, max_x, max_y, i;
+      
+      min_x = max_x = points[0].x;
+      min_y = max_y = points[0].y;
+      
+       for (i = 1; i < npoints; i++)
+         {
+           min_x = MIN (min_x, points[i].x);
+           max_x = MAX (max_x, points[i].x);
+           min_y = MIN (min_y, points[i].y);
+           max_y = MAX (max_y, points[i].y);
+         }
+       
+       add_damage (offscreen, min_x, min_y,
+                   max_x - min_x,
+                   max_y - min_y);
+    }
+}
+
+static void
+gdk_offscreen_window_draw_segments (GdkDrawable  *drawable,
+                                   GdkGC        *gc,
+                                   GdkSegment   *segs,
+                                   gint          nsegs)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+  gdk_draw_segments (real_drawable,
+                    gc,
+                    segs,
+                    nsegs);
+
+  if (nsegs > 0)
+    {
+      int min_x, min_y, max_x, max_y, i;
+      
+      min_x = max_x = segs[0].x1;
+      min_y = max_y = segs[0].y1;
+      
+       for (i = 1; i < nsegs; i++)
+         {
+           min_x = MIN (min_x, segs[i].x1);
+           max_x = MAX (max_x, segs[i].x1);
+           min_x = MIN (min_x, segs[i].x2);
+           max_x = MAX (max_x, segs[i].x2);
+           min_y = MIN (min_y, segs[i].y1);
+           max_y = MAX (max_y, segs[i].y1);
+           min_y = MIN (min_y, segs[i].y2);
+           max_y = MAX (max_y, segs[i].y2);
+         }
+       
+       add_damage (offscreen, min_x, min_y,
+                   max_x - min_x,
+                   max_y - min_y);
+    }
+
+}
+
+static void
+gdk_offscreen_window_draw_lines (GdkDrawable  *drawable,
+                                GdkGC        *gc,
+                                GdkPoint     *points,
+                                gint          npoints)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+  gdk_draw_lines (real_drawable,
+                 gc,
+                 points,
+                 npoints);
+
+  /* Hard to compute the minimal size, as we don't know the line
+     width, and since joins are hard to calculate.
+     Its not that often used anyway, damage it all */
+  add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_image (GdkDrawable *drawable,
+                                GdkGC        *gc,
+                                GdkImage    *image,
+                                gint          xsrc,
+                                gint          ysrc,
+                                gint          xdest,
+                                gint          ydest,
+                                gint          width,
+                                gint          height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+  gdk_draw_image (real_drawable,
+                 gc,
+                 image,
+                 xsrc,
+                 ysrc,
+                 xdest,
+                 ydest,
+                 width,
+                 height);
+
+  add_damage (offscreen, xdest, ydest, width, height);
+}
+
+
+static void
+gdk_offscreen_window_draw_pixbuf (GdkDrawable *drawable,
+                                 GdkGC       *gc,
+                                 GdkPixbuf   *pixbuf,
+                                 gint         src_x,
+                                 gint         src_y,
+                                 gint         dest_x,
+                                 gint         dest_y,
+                                 gint         width,
+                                 gint         height,
+                                 GdkRgbDither dither,
+                                 gint         x_dither,
+                                 gint         y_dither)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+  
+  gdk_draw_pixbuf (real_drawable,
+                  gc,
+                  pixbuf,
+                  src_x,
+                  src_y,
+                  dest_x,
+                  dest_y,
+                  width,
+                  height,
+                  dither,
+                  x_dither,
+                  y_dither);
+
+  add_damage (offscreen, dest_x, dest_y, width, height);
+
+}
+
+void 
+_gdk_offscreen_window_new (GdkWindow     *window,
+                          GdkScreen     *screen,
+                          GdkVisual     *visual,
+                          GdkWindowAttr *attributes,
+                          gint           attributes_mask)
+{
+  GdkWindowObject *parent_private;
+  GdkWindowObject *private;
+  GdkOffscreenWindow *offscreen;
+
+  g_return_if_fail (attributes != NULL);
+
+  if (attributes->wclass != GDK_INPUT_OUTPUT)
+    return; /* Can't support input only offscreens */
+  
+  private = (GdkWindowObject *)window;
+
+  if (private->parent != NULL && GDK_WINDOW_DESTROYED (private->parent))
+    return;
+
+  parent_private = (GdkWindowObject*) private->parent;
+  private->impl = g_object_new (GDK_TYPE_OFFSCREEN_WINDOW, NULL);
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  offscreen->wrapper = window;
+
+  offscreen->screen = screen;
+
+  if (attributes_mask & GDK_WA_COLORMAP)
+    offscreen->colormap = g_object_ref (attributes->colormap);
+  else
+    {
+      if (gdk_screen_get_system_visual (screen) == visual)
+       {
+         offscreen->colormap = gdk_screen_get_system_colormap (screen);
+         g_object_ref (offscreen->colormap);
+       }
+      else
+       offscreen->colormap = gdk_colormap_new (visual, FALSE);
+    }
+
+  offscreen->pixmap = gdk_pixmap_new ((GdkDrawable *)private->parent,
+                                     private->width,
+                                     private->height,
+                                     private->depth);
+}
+
+static gboolean
+gdk_offscreen_window_reparent (GdkWindow *window,
+                              GdkWindow *new_parent,
+                              gint       x,
+                              gint       y)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *new_parent_private = (GdkWindowObject *)new_parent;
+  GdkWindowObject *old_parent;
+  GdkOffscreenWindow *offscreen;
+  gboolean was_mapped;
+
+  if (new_parent)
+    {
+      /* No input-output children of input-only windows */
+      if (new_parent_private->input_only && !private->input_only)
+       return FALSE;
+      
+      /* Don't create loops in hierarchy */
+      if (is_parent_of (window, new_parent))
+       return FALSE;
+    }
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
+
+  gdk_window_hide (window);
+
+  if (private->parent)
+    private->parent->children = g_list_remove (private->parent->children, window);
+
+  old_parent = private->parent;
+  private->parent = new_parent_private;
+  private->x = x;
+  private->y = y;
+
+  if (new_parent_private)
+    private->parent->children = g_list_prepend (private->parent->children, window);
+
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+  if (old_parent)
+    _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (old_parent));
+  
+  return was_mapped;
+}
+
+static gint
+gdk_offscreen_window_get_origin (GdkWindow *window,
+                                gint      *x,
+                                gint      *y)
+{
+  if (x)
+    *x = 0;
+  if (y)
+    *y = 0;
+
+  return TRUE;
+}
+
+/**
+ * gdk_window_get_offscreen_pixmap:
+ * @window: a #GdkWindow
+ *
+ * Gets the offscreen pixmap that an offscreen window renders into. If
+ * you need to keep this around over window resizes, you need to add a
+ * reference to it.
+ *
+ * Returns: The offscreen pixmap, or NULL if not offscreen
+ **/
+GdkPixmap *
+gdk_window_get_offscreen_pixmap (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+  
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
+    return NULL;
+  
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  return offscreen->pixmap;
+}
+
+static void
+gdk_offscreen_window_raise (GdkWindow *window)
+{
+  /* gdk_window_raise already changed the stacking order */
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_lower (GdkWindow *window)
+{
+  /* gdk_window_lower already changed the stacking order */
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_move_resize_internal (GdkWindow *window,
+                                          gint       x,
+                                          gint       y,
+                                          gint       width,
+                                          gint       height,
+                                          gboolean   send_expose_events)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+  gint dx, dy, dw, dh;
+  GdkGC *gc;
+  GdkPixmap *old_pixmap;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (width < 1)
+    width = 1;
+  if (height < 1)
+    height = 1;
+
+  if (private->destroyed)
+    return;
+
+  dx = x - private->x;
+  dy = y - private->y;
+  dw = width - private->width;
+  dh = height - private->height;
+
+  private->x = x;
+  private->y = y;
+
+  if (private->width != width ||
+      private->height != height)
+    {
+      private->width = width;
+      private->height = height;
+      
+      old_pixmap = offscreen->pixmap;
+      offscreen->pixmap = gdk_pixmap_new (GDK_DRAWABLE (old_pixmap),
+                                         width,
+                                         height,
+                                         private->depth);
+
+      gc = _gdk_drawable_get_scratch_gc (offscreen->pixmap, FALSE);
+      gdk_draw_drawable (offscreen->pixmap,
+                        gc,
+                        old_pixmap,
+                        0,0, 0, 0,
+                        -1, -1);
+      g_object_unref (old_pixmap);
+    }
+  
+  if (GDK_WINDOW_IS_MAPPED (private))
+    {
+      // TODO: Only invalidate new area, i.e. for larger windows
+      gdk_window_invalidate_rect (window, NULL, TRUE);
+      _gdk_syntesize_crossing_events_for_geometry_change (window);
+    }
+}
+
+static void
+gdk_offscreen_window_move_resize (GdkWindow *window,
+                                  gboolean   with_move,
+                                 gint       x,
+                                  gint       y,
+                                 gint       width,
+                                  gint       height)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (!with_move)
+    {
+      x = private->x;
+      y = private->y;
+    }
+
+  if (width < 0)
+    width = private->width;
+
+  if (height < 0)
+    height = private->height;
+
+  gdk_offscreen_window_move_resize_internal (window, x, y,
+                                            width, height,
+                                            TRUE);
+}
+
+static void
+gdk_offscreen_window_show (GdkWindow *window, gboolean raise)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  if (GDK_WINDOW_IS_MAPPED (window))
+    return;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  private->state = 0;
+
+  /* gdk_window_show already changed the stacking order if needed */
+
+  if (private->event_mask & GDK_STRUCTURE_MASK)
+    _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+  
+  if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+    _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+
+  if (gdk_window_is_viewable (window))
+    _gdk_syntesize_crossing_events_for_geometry_change (window);
+  
+  gdk_window_clear_area_e (window, 0, 0,
+                          private->width, private->height);
+}
+
+
+static void
+gdk_offscreen_window_hide (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  GdkOffscreenWindow *offscreen;
+  GdkDisplay *display;
+
+  g_return_if_fail (window != NULL);
+
+  private = (GdkWindowObject*) window;
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (!GDK_WINDOW_IS_MAPPED (private))
+    return;
+  
+  /* May need to break grabs on children */
+  display = gdk_drawable_get_display (window);
+  
+  if (display->pointer_grab.window != NULL)
+    {
+      if (is_parent_of (window, display->pointer_grab.window))
+       {
+         /* Call this ourselves, even though gdk_display_pointer_ungrab
+            does so too, since we want to pass implicit == TRUE so the
+            broken grab event is generated */
+         _gdk_display_unset_has_pointer_grab (display,
+                                              TRUE,
+                                              FALSE,
+                                              GDK_CURRENT_TIME);
+         gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+       }
+    }
+
+  if (private->event_mask & GDK_STRUCTURE_MASK)
+    _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+  
+  if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+    _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+  
+  private->state = GDK_WINDOW_STATE_WITHDRAWN;
+  
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_withdraw (GdkWindow *window)
+{
+}
+
+static GdkEventMask
+gdk_offscreen_window_get_events (GdkWindow *window)
+{
+  return 0;
+}
+
+static void
+gdk_offscreen_window_set_events (GdkWindow       *window,
+                                GdkEventMask     event_mask)
+{
+}
+
+static GdkGC *
+setup_backing_rect_gc (GdkWindow *window, int x_offset, int y_offset)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkGC *gc;
+
+  if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
+    {
+      x_offset += private->x;
+      y_offset += private->y;
+      
+      return setup_backing_rect_gc (GDK_WINDOW (private->parent), x_offset, y_offset);
+    }
+  else if (private->bg_pixmap &&
+          private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+          private->bg_pixmap != GDK_NO_BG)
+    {
+      guint gc_mask;
+      GdkGCValues gc_values;
+
+      gc_values.fill = GDK_TILED;
+      gc_values.tile = private->bg_pixmap;
+      gc_values.ts_x_origin = -x_offset;
+      gc_values.ts_y_origin = -y_offset;
+
+      gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
+
+      return gdk_gc_new_with_values (window, &gc_values, gc_mask);
+    }
+  else
+    {
+      gc = _gdk_drawable_get_scratch_gc (window, FALSE);
+      g_object_ref (gc);
+      gdk_gc_set_foreground (gc, &private->bg_color);
+      return gc;
+    }
+}
+
+static void
+gdk_offscreen_window_clear_area (GdkWindow *window,
+                                gint       x,
+                                gint       y,
+                                gint       width,
+                                gint       height,
+                                gboolean   send_expose)
+{
+  GdkGC *gc;
+  
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  /* Actual drawing is done by gdkwindow.c */
+
+  gc = setup_backing_rect_gc (window, 0, 0);
+  gdk_draw_rectangle (window, gc, TRUE, x, y, width, height);
+  g_object_unref (gc);
+  
+  if (send_expose)
+    {
+      GdkRectangle visible, rect;
+
+      visible.x = visible.y = 0;
+      gdk_drawable_get_size (GDK_DRAWABLE (window), &visible.width, &visible.height);
+
+      rect.x = x;
+      rect.y = x;
+      rect.width = width;
+      rect.height = height;
+
+      gdk_rectangle_intersect (&rect, &visible, &rect);
+
+      gdk_window_invalidate_rect (window, &rect, TRUE);
+    }
+}
+
+static void
+gdk_offscreen_window_set_background (GdkWindow      *window,
+                                    const GdkColor *color)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkColormap *colormap = gdk_drawable_get_colormap (window);
+
+  private->bg_color = *color;
+  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
+
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+
+  private->bg_pixmap = NULL;
+}
+
+static void
+gdk_offscreen_window_set_back_pixmap (GdkWindow *window,
+                                     GdkPixmap *pixmap)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  if (pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG &&
+      !gdk_drawable_get_colormap (pixmap))
+    {
+      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+      return;
+    }
+
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+
+  private->bg_pixmap = pixmap;
+
+  if (pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_ref (pixmap);
+}
+
+static void
+gdk_offscreen_window_shape_combine_mask (GdkWindow *window,
+                                         GdkBitmap *mask,
+                                         gint       x,
+                                         gint       y)
+{
+}
+
+static void
+gdk_offscreen_window_shape_combine_region (GdkWindow       *window,
+                                           const GdkRegion *shape_region,
+                                           gint             offset_x,
+                                           gint             offset_y)
+{
+}
+
+static void
+gdk_offscreen_window_set_child_shapes (GdkWindow *window)
+{
+}
+
+static void
+gdk_offscreen_window_merge_child_shapes (GdkWindow *window)
+{
+}
+
+static gboolean
+gdk_offscreen_window_set_static_gravities (GdkWindow *window,
+                                          gboolean   use_static)
+{
+  return TRUE;
+}
+
+static void
+gdk_offscreen_window_set_cursor (GdkWindow *window,
+                                GdkCursor *cursor)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (offscreen->cursor)
+    {
+      gdk_cursor_unref (offscreen->cursor);
+      offscreen->cursor = NULL;
+    }
+
+  if (cursor)
+    offscreen->cursor = gdk_cursor_ref (cursor);
+
+  /* TODO: The cursor is never actually used... */
+}
+
+static void
+gdk_offscreen_window_get_geometry (GdkWindow *window,
+                                  gint      *x,
+                                  gint      *y,
+                                  gint      *width,
+                                  gint      *height,
+                                  gint      *depth)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
+
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      if (x)
+       *x = private->x;
+      if (y)
+       *y = private->y;
+      if (width)
+       *width = private->width;
+      if (height)
+       *height = private->height;
+      if (depth)
+       *depth = private->depth;
+    }
+}
+
+/**
+ * gdk_window_set_offscreen_hooks:
+ * @offscreen_window: a offscreen #GdkWindow
+ * @hooks:  a table of pointers to functions for handling offscreen
+ *          window coordinates translations
+ *
+ * Sets the parent-to-offscreen-child and offscreen-child-to-parent coordinate
+ * translation functions for offscreen windows.
+ *
+ * This function is useful for complex widgets employing
+ * offscreen windows.
+ *
+ * Since: 2.16
+ */
+void
+gdk_window_set_offscreen_hooks (GdkWindow  *offscreen_window,
+                                const GdkOffscreenChildHooks *hooks)
+{
+  GdkWindowObject *private;
+
+  g_return_if_fail (GDK_IS_WINDOW (offscreen_window));
+  g_return_if_fail (hooks != NULL);
+
+  private = (GdkWindowObject *) offscreen_window;
+
+  private->offscreen_hooks = hooks;
+}
+
+static gboolean
+gdk_offscreen_window_queue_antiexpose (GdkWindow *window,
+                                      GdkRegion *area)
+{
+  return FALSE;
+}
+
+static void
+gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
+{
+  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gdk_offscreen_window_finalize;
+
+  drawable_class->create_gc = gdk_offscreen_window_create_gc;
+  drawable_class->_copy_to_image = gdk_offscreen_window_copy_to_image;
+  drawable_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface;
+  drawable_class->set_colormap = gdk_offscreen_window_set_colormap;
+  drawable_class->get_colormap = gdk_offscreen_window_get_colormap;
+  drawable_class->get_depth = gdk_offscreen_window_get_depth;
+  drawable_class->get_screen = gdk_offscreen_window_get_screen;
+  drawable_class->get_visual = gdk_offscreen_window_get_visual;
+  drawable_class->get_source_drawable = gdk_offscreen_window_get_source_drawable;
+  drawable_class->get_composite_drawable = gdk_offscreen_window_get_composite_drawable;
+
+  drawable_class->draw_rectangle = gdk_offscreen_window_draw_rectangle;
+  drawable_class->draw_arc = gdk_offscreen_window_draw_arc;
+  drawable_class->draw_polygon = gdk_offscreen_window_draw_polygon;
+  drawable_class->draw_text = gdk_offscreen_window_draw_text;
+  drawable_class->draw_text_wc = gdk_offscreen_window_draw_text_wc;
+  drawable_class->draw_drawable = gdk_offscreen_window_draw_drawable;
+  drawable_class->draw_points = gdk_offscreen_window_draw_points;
+  drawable_class->draw_segments = gdk_offscreen_window_draw_segments;
+  drawable_class->draw_lines = gdk_offscreen_window_draw_lines;
+  drawable_class->draw_image = gdk_offscreen_window_draw_image;
+  drawable_class->draw_pixbuf = gdk_offscreen_window_draw_pixbuf;
+}
+
+static void
+gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
+{
+  iface->show = gdk_offscreen_window_show;
+  iface->hide = gdk_offscreen_window_hide;
+  iface->withdraw = gdk_offscreen_window_withdraw;
+  iface->raise = gdk_offscreen_window_raise;
+  iface->lower = gdk_offscreen_window_lower;
+  iface->move_resize = gdk_offscreen_window_move_resize;
+  iface->set_background = gdk_offscreen_window_set_background;
+  iface->set_back_pixmap = gdk_offscreen_window_set_back_pixmap;
+  iface->get_events = gdk_offscreen_window_get_events;
+  iface->set_events = gdk_offscreen_window_set_events;
+  iface->clear_area = gdk_offscreen_window_clear_area;
+  iface->reparent = gdk_offscreen_window_reparent;
+  iface->set_cursor = gdk_offscreen_window_set_cursor;
+  iface->get_geometry = gdk_offscreen_window_get_geometry;
+  iface->shape_combine_mask = gdk_offscreen_window_shape_combine_mask;
+  iface->shape_combine_region = gdk_offscreen_window_shape_combine_region;
+  iface->set_child_shapes = gdk_offscreen_window_set_child_shapes;
+  iface->merge_child_shapes = gdk_offscreen_window_merge_child_shapes;
+  iface->set_static_gravities = gdk_offscreen_window_set_static_gravities;
+  iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
+  iface->get_origin = gdk_offscreen_window_get_origin;
+}
+
+#define __GDK_OFFSCREEN_WINDOW_C__
+#include "gdkaliasdef.c"
index a38640374b66dcf694d5b6a83d90d80198e691b5..24efca8b2918dbff6420745fad7dfd363773b69c 100644 (file)
@@ -214,7 +214,8 @@ get_cairo_context (GdkPangoRenderer *gdk_renderer,
                                  priv->cr,
                                  color,
                                  priv->stipple[part],
-                                 priv->gc_changed);
+                                 priv->gc_changed,
+                                 priv->drawable);
        }
 
       priv->last_part = part;
index c717b9afb825c57a0e96ebff257d33a886c2f53d..806a5ca8d5c687dbfcba34a68d9f1776acfb78d6 100644 (file)
@@ -229,6 +229,48 @@ gdk_pixmap_finalize (GObject *object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+GdkPixmap *
+gdk_pixmap_new (GdkDrawable *drawable,
+                gint         width,
+                gint         height,
+                gint         depth)
+{
+  GdkDrawable *source_drawable;
+
+  source_drawable = _gdk_drawable_get_source_drawable (drawable);
+  return _gdk_pixmap_new (source_drawable, width, height, depth);
+}
+
+GdkPixmap *
+gdk_bitmap_create_from_data (GdkDrawable *drawable,
+                             const gchar *data,
+                             gint         width,
+                             gint         height)
+{
+  GdkDrawable *source_drawable;
+
+  source_drawable = _gdk_drawable_get_source_drawable (drawable);
+  return _gdk_bitmap_create_from_data (source_drawable, data, width, height);
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_data (GdkDrawable    *drawable,
+                             const gchar    *data,
+                             gint            width,
+                             gint            height,
+                             gint            depth,
+                             const GdkColor *fg,
+                             const GdkColor *bg)
+{
+  GdkDrawable *source_drawable;
+
+  source_drawable = _gdk_drawable_get_source_drawable (drawable);
+  return _gdk_pixmap_create_from_data (source_drawable,
+                                       data, width, height,
+                                       depth, fg,bg);
+}
+
+
 static GdkGC *
 gdk_pixmap_create_gc (GdkDrawable     *drawable,
                       GdkGCValues     *values,
index 66b83ae85daf15729d5e22729a2f626f9f646d26..fabe972e57983b52aa29b2efc6b54fa5292ff54d 100644 (file)
 #include "gdkscreen.h"
 #include "gdkalias.h"
 
-#define USE_BACKING_STORE      /* Appears to work on Win32, too, now. */
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h"           /* For workaround */
+#endif
+
+#include "math.h"
+
+/* Not all GdkWindows have a corresponding native window.
+ * Instead some draw into the nearest parent that has whatss
+ * called an "impl", i.e. the implementation window.
+ * For toplevel window system windows the impl is always native
+ * window, but child windows can also have native windows as
+ * this is sometimes necessary. Furthermore, offscreen windows
+ * (type GDK_WINDOW_OFFSCREEN) have an impl of type
+ * GdkOffscreenWindow rather than a backend implementation native
+ * window. Such windows draw into an offscreen pixmap instead
+ * of a window and collect damage that lets you paint it where
+ * you want.
+ *
+ * All GdkWindow track their position, size, clip region and
+ * absolute position in the impl window. For child window with
+ * native windows the clip region is set on the native window
+ * as a window shape to make it clip against other non-native windows.
+ */  
 
-typedef struct _GdkWindowPaint GdkWindowPaint;
+#define USE_BACKING_STORE      /* Appears to work on Win32, too, now. */
 
 struct _GdkWindowPaint
 {
@@ -46,27 +68,10 @@ struct _GdkWindowPaint
   gint x_offset;
   gint y_offset;
   cairo_surface_t *surface;
+  guint uses_implicit : 1;
 };
 
-typedef struct {
-  GdkRegion *old_region;
-  gint old_clip_x_origin;
-  gint old_clip_y_origin;
-  gint x_offset;
-  gint y_offset;
-} GdkWindowClipData;
-
-struct _GdkWindowRedirect
-{
-  GdkWindowObject *redirected;
-  GdkDrawable *pixmap;
-  gint src_x;
-  gint src_y;
-  gint dest_x;
-  gint dest_y;
-  gint width;
-  gint height;
-};
+/* Global info */
 
 static GdkGC *gdk_window_create_gc      (GdkDrawable     *drawable,
                                          GdkGCValues     *values,
@@ -180,6 +185,8 @@ static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
                                           gint         height);
 
 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
+static void             gdk_window_set_cairo_clip    (GdkDrawable *drawable,
+                                                     cairo_t *cr);
 
 static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
                                          gint            *width,
@@ -192,6 +199,7 @@ static void         gdk_window_real_set_colormap (GdkDrawable *drawable,
                                                  GdkColormap *cmap);
 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
 
+static GdkDrawable* gdk_window_get_source_drawable    (GdkDrawable *drawable);
 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
                                                       gint         x,
                                                       gint         y,
@@ -212,26 +220,20 @@ static void gdk_window_clear_backing_rect (GdkWindow *window,
                                           gint       y,
                                           gint       width,
                                           gint       height);
-static void setup_redirect_clip           (GdkWindow         *window,
-                                          GdkGC             *gc,
-                                          GdkWindowClipData *data);
-static void reset_redirect_clip           (GdkWindow         *offscreen,
-                                          GdkGC             *gc,
-                                          GdkWindowClipData *data);
 static void gdk_window_redirect_free      (GdkWindowRedirect *redirect);
 static void apply_redirect_to_children    (GdkWindowObject   *private,
                                           GdkWindowRedirect *redirect);
 static void remove_redirect_from_children (GdkWindowObject   *private,
                                           GdkWindowRedirect *redirect);
-static GdkRegion *_gdk_window_calculate_full_clip_region (GdkWindow *window,
-                                                         GdkWindow *base_window,
-                                                         GdkGC *gc,
-                                                         gboolean do_children,
-                                                         gint *base_x_offset,
-                                                         gint *base_y_offset);
 
+static void recompute_visible_regions (GdkWindowObject *private,
+                                      gboolean recalculate_siblings,
+                                      gboolean recalculate_children);
+  
 static gpointer parent_class = NULL;
 
+static const cairo_user_data_key_t gdk_window_cairo_key;
+
 GType
 gdk_window_object_get_type (void)
 {
@@ -281,6 +283,9 @@ gdk_window_init (GdkWindowObject *window)
   window->window_type = GDK_WINDOW_CHILD;
 
   window->state = GDK_WINDOW_STATE_WITHDRAWN;
+  window->width = 1;
+  window->height = 1;
+  window->toplevel_window_type = -1;
 }
 
 static GQuark quark_pointer_window = 0;
@@ -318,9 +323,11 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
   drawable_class->get_visual = gdk_window_real_get_visual;
   drawable_class->_copy_to_image = gdk_window_copy_to_image;
   drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
+  drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
   drawable_class->get_clip_region = gdk_window_get_clip_region;
   drawable_class->get_visible_region = gdk_window_get_visible_region;
   drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
+  drawable_class->get_source_drawable = gdk_window_get_source_drawable;
 
   quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
 }
@@ -345,12 +352,264 @@ gdk_window_finalize (GObject *object)
        _gdk_window_destroy (window, TRUE);
     }
 
-  g_object_unref (obj->impl);
-  obj->impl = NULL;
+  if (obj->impl)
+    {
+      g_object_unref (obj->impl);
+      obj->impl = NULL;
+    }
+
+  if (obj->cursor)
+    gdk_cursor_unref (obj->cursor);
+
+  if (obj->colormap)
+    g_object_unref (obj->colormap);
   
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static gboolean
+gdk_window_is_offscreen (GdkWindowObject *window)
+{
+  return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
+}
+
+static GdkWindowObject *
+gdk_window_get_impl_window (GdkWindowObject *window)
+{
+  while (window->parent->impl == window->impl)
+    window = window->parent;
+
+  return window;
+}
+
+GdkWindow *
+_gdk_window_get_impl_window (GdkWindow *window)
+{
+  return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
+}
+
+static gboolean
+gdk_window_has_impl (GdkWindowObject *window)
+{
+  return window->parent == NULL || window->parent->impl != window->impl;
+}
+
+gboolean
+_gdk_window_has_impl (GdkWindow *window)
+{
+  return gdk_window_has_impl ((GdkWindowObject *)window);
+}
+
+static gboolean
+gdk_window_has_no_impl (GdkWindowObject *window)
+{
+  return window->parent->impl == window->impl;
+}
+
+static void
+remove_child_area (GdkWindowObject *private,
+                  GdkWindowObject *until,
+                  GdkRegion *region)
+{
+  GdkWindowObject *child;
+  GdkRegion *child_region;
+  GdkRectangle r;
+  GList *l;
+  
+  for (l = private->children; l; l = l->next)
+    {
+      child = l->data;
+
+      if (child == until)
+       break;
+      
+      if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
+       continue;
+
+      /* Ignore offscreen children, as they don't draw in their parent and
+       * don't take part in the clipping */
+      if (gdk_window_is_offscreen (child))
+       continue;
+
+      r.x = child->x;
+      r.y = child->y;
+      r.width = child->width;
+      r.height = child->height;
+      
+      child_region = gdk_region_rectangle (&r);
+      gdk_region_subtract (region, child_region);
+      gdk_region_destroy (child_region);
+    }
+}
+
+static void
+recompute_visible_regions_internal (GdkWindowObject *private,
+                                   gboolean recalculate_clip,
+                                   gboolean recalculate_siblings,
+                                   gboolean recalculate_children)
+{
+  GdkRectangle r;
+  GList *l;
+  GdkWindowObject *child;
+  GdkRegion *new_clip;
+  gboolean clip_region_changed;
+  gboolean abs_pos_changed;
+  int old_abs_x, old_abs_y;
+
+  old_abs_x = private->abs_x;
+  old_abs_y = private->abs_y;
+  
+  /* Update absolute position */
+  if (gdk_window_has_impl (private))
+    {
+      /* Native window starts here */
+      private->abs_x = 0;
+      private->abs_y = 0;
+    }
+  else
+    {
+      private->abs_x = private->parent->abs_x + private->x;
+      private->abs_y = private->parent->abs_y + private->y;
+    }
+
+  abs_pos_changed =
+    private->abs_x != old_abs_x ||
+    private->abs_y != old_abs_y;
+
+  /* Update clip region based on:
+   * parent clip
+   * window size
+   * siblings in parents above window
+   */
+  clip_region_changed = FALSE;
+  if (recalculate_clip)
+    {
+      /* Calculate visible region (sans children) in parent window coords */
+      r.x = private->x;
+      r.y = private->y;
+      r.width = private->width;
+      r.height = private->height;
+      new_clip = gdk_region_rectangle (&r);
+      
+      if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+       {
+         gdk_region_intersect (new_clip, private->parent->clip_region);
+         
+         /* Remove all overlapping children from parent */
+         remove_child_area (private->parent, private, new_clip);
+       }
+      
+      /* Convert from parent coords to window coords */
+      gdk_region_offset (new_clip, -private->x, -private->y);
+
+      if (private->clip_region == NULL ||
+         !gdk_region_equal (private->clip_region, new_clip))
+       clip_region_changed = TRUE;
+       
+      if (private->clip_region)
+       gdk_region_destroy (private->clip_region);
+      private->clip_region = new_clip;
+
+      private->clip_region_with_children = gdk_region_copy (private->clip_region);
+      remove_child_area (private, NULL, private->clip_region_with_children);
+    }
+
+  /* Update all children, recursively. */
+  if (abs_pos_changed || clip_region_changed || recalculate_children)
+    {
+      for (l = private->children; l; l = l->next)
+       {
+         child = l->data;
+         /* Only recalculate clip if the the clip region changed, otherwise
+          * there is no way the child clip region could change (its has not e.g. moved)
+          * Except if recalculate_children is set to force child updates
+          */
+         recompute_visible_regions_internal (child, recalculate_clip && (clip_region_changed || recalculate_children), FALSE, FALSE);
+       }
+    }
+
+  if (clip_region_changed &&
+      gdk_window_has_impl (private) &&
+      /* Not for offscreens */
+      private->window_type != GDK_WINDOW_OFFSCREEN &&
+      /* or for toplevels */
+      private->parent != NULL &&
+      GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT
+      )
+    {
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
+    }
+      
+  
+  if (recalculate_siblings &&
+      private->parent != NULL &&
+      GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+    {
+      /* If we moved a child window in parent or changed the stacking order, then we
+       * need to recompute the visible area of all the other children in the parent
+       */
+      for (l = private->parent->children; l; l = l->next)
+       {
+         child = l->data;
+
+         if (child != private)
+           recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
+       }
+
+      /* We also need to recompute the _with_children clip for the parent */
+      recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
+    }
+
+  if (private->cairo_surface)
+    {
+      int width, height;
+
+      /* It would be nice if we had some cairo support here so we
+        could set the clip rect on the cairo surface */
+      width = private->abs_x + private->width;
+      height = private->abs_y + private->height;
+
+      _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
+                                            width, height);
+      cairo_surface_set_device_offset (private->cairo_surface, 
+                                      private->abs_x,
+                                      private->abs_y);
+    }
+}
+
+/* Call this when private has changed in one or more of these ways:
+ *  size changed
+ *  window moved
+ *  new window added
+ *  stacking order of window changed
+ *  child deleted
+ *
+ * It will recalculate abs_x/y and the clip regions
+ *
+ * Unless the window didn't change stacking order or size/pos, pass in TRUE
+ * for recalculate_siblings. (Mostly used internally for the recursion)
+ * 
+ * If a child window was removed (and you can't use that child for
+ * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
+ */
+static void
+recompute_visible_regions (GdkWindowObject *private,
+                          gboolean recalculate_siblings,
+                          gboolean recalculate_children)
+{
+  recompute_visible_regions_internal (private,
+                                     TRUE,
+                                     recalculate_siblings,
+                                     recalculate_children);
+}
+
+void
+_gdk_window_update_size (GdkWindow *window)
+{
+  recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
+}
+
+
 /**
  * gdk_window_new:
  * @parent: a #GdkWindow, or %NULL to create the window as a child of
@@ -371,25 +630,225 @@ gdk_window_new (GdkWindow     *parent,
                gint           attributes_mask)
 {
   GdkWindow *window;
-  GdkWindowObject *private, *parent_private;
-
-  g_return_val_if_fail (parent == NULL || GDK_IS_WINDOW (parent), NULL);
+  GdkWindowObject *private;
+  GdkScreen *screen;
+  GdkVisual *visual;
+  int x, y, depth;
+  gboolean native;
+  GdkEventMask event_mask;
+  
   g_return_val_if_fail (attributes != NULL, NULL);
+  
+  if (!parent)
+    {
+      GDK_NOTE (MULTIHEAD,
+               g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
+      
+      screen = gdk_screen_get_default ();
+      parent = gdk_screen_get_root_window (screen);
+    }
+  else
+    screen = gdk_drawable_get_screen (parent);
+
+  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
+  
+  if (GDK_WINDOW_DESTROYED (parent))
+    return NULL;
+
+  window = g_object_new (GDK_TYPE_WINDOW, NULL);
+  private = (GdkWindowObject *) window;
 
-  window = _gdk_window_new (parent, attributes, attributes_mask);
-  g_return_val_if_fail (window != NULL, window);
+  /* Windows with a foreign parent are treated as if they are children
+   * of the root window, except for actual creation.
+   */
+  if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
+    parent = gdk_screen_get_root_window (screen);
+
+  private->parent = (GdkWindowObject *)parent;
+
+  private->accept_focus = TRUE;
+  private->focus_on_map = TRUE;
+
+  if (attributes_mask & GDK_WA_X)
+    x = attributes->x;
+  else
+    x = 0;
+  
+  if (attributes_mask & GDK_WA_Y)
+    y = attributes->y;
+  else
+    y = 0;
+  
+  private->x = x;
+  private->y = y;
+  private->width = (attributes->width > 1) ? (attributes->width) : (1);
+  private->height = (attributes->height > 1) ? (attributes->height) : (1);
+
+#ifdef GDK_WINDOWING_X11
+  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows 
+   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
+   */
+  if (attributes->wclass == GDK_INPUT_ONLY &&
+      GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT &&
+      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
+    {
+      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
+      attributes->wclass = GDK_INPUT_OUTPUT;
+    }
+#endif
+  
+  if (attributes->wclass == GDK_INPUT_ONLY)
+    {
+      /* Backwards compatiblity - we've always ignored
+       * attributes->window_type for input-only windows
+       * before
+       */
+      if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
+       private->window_type = GDK_WINDOW_TEMP;
+      else
+       private->window_type = GDK_WINDOW_CHILD;
+    }
+  else
+    private->window_type = attributes->window_type;
+
+  /* Sanity checks */
+  switch (private->window_type)
+    {
+    case GDK_WINDOW_TOPLEVEL:
+    case GDK_WINDOW_DIALOG:
+    case GDK_WINDOW_TEMP:
+      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+       g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
+                  "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+    case GDK_WINDOW_CHILD:
+    case GDK_WINDOW_OFFSCREEN:
+      break;
+    default:
+      g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
+      return NULL;
+    }
+  
+  if (attributes_mask & GDK_WA_VISUAL)
+    visual = attributes->visual;
+  else
+    visual = gdk_screen_get_system_visual (screen);
+
+  private->event_mask = attributes->event_mask;
+
+  if (attributes->wclass == GDK_INPUT_OUTPUT)
+    {
+      depth = visual->depth;
 
-  /* Inherit redirection from parent */
-  if (parent != NULL)
+      if (attributes_mask & GDK_WA_COLORMAP)
+       private->colormap = g_object_ref (attributes->colormap);
+      
+      private->input_only = FALSE;
+      private->depth = depth;
+  
+      private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
+      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
+
+      private->bg_pixmap = NULL;
+    }
+  else
+    {
+      depth = 0;
+      private->depth = 0;
+      private->input_only = TRUE;
+    }
+
+  if (private->parent)
+    private->parent->children = g_list_prepend (private->parent->children, window);
+
+  native = FALSE; /* Default */
+  if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    native = TRUE; /* Always use native windows for toplevels */
+
+  if (private->window_type == GDK_WINDOW_OFFSCREEN)
+    {
+      _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
+    }
+  else if (native)
+    {
+      if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+       event_mask =
+         GDK_EXPOSURE_MASK |
+         GDK_POINTER_MOTION_MASK |
+         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+         GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
+         GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
+         GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK |
+         GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SCROLL_MASK;
+      else
+       event_mask = GDK_EXPOSURE_MASK;
+      
+      /* Create the impl */
+      _gdk_window_impl_new (window, screen, visual, event_mask, attributes, attributes_mask);
+    }
+  else
     {
-      parent_private = GDK_WINDOW_OBJECT (parent);
-      private = GDK_WINDOW_OBJECT (window);
-      private->redirect = parent_private->redirect;
+      private->impl = private->parent->impl;
     }
+
+  recompute_visible_regions (private, TRUE, FALSE);
   
+  if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+    {
+      /* Inherit redirection from parent */
+      private->redirect = private->parent->redirect;
+    }
+    
   return window;
 }
 
+static gboolean
+is_parent_of (GdkWindow *parent,
+              GdkWindow *child)
+{
+  GdkWindow *w;
+
+  w = child;
+  while (w != NULL)
+    {
+      if (w == parent)
+       return TRUE;
+
+      w = gdk_window_get_parent (w);
+    }
+
+  return FALSE;
+}
+
+static void
+change_impl (GdkWindowObject *private,
+            GdkDrawable *new)
+{
+  GList *l;
+  GdkWindowObject *child;
+  gboolean show;
+  GdkDrawable *old_impl;
+
+  old_impl = private->impl;
+  private->impl = new;
+  
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      if (child->impl == old_impl)
+       change_impl (child, new);
+      else
+       {
+         show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
+                                                                     (GdkWindow *)private,
+                                                                     child->x, child->y);
+         if (show)
+           gdk_window_show_unraised ((GdkWindow *)child);
+       }
+    }
+
+}
+
 /**
  * gdk_window_reparent:
  * @window: a #GdkWindow
@@ -408,19 +867,42 @@ gdk_window_reparent (GdkWindow *window,
                     gint       y)
 {
   GdkWindowObject *private;
-  gboolean show;
-
+  GdkWindowObject *new_parent_private;
+  GdkWindowObject *old_parent;
+  gboolean show, was_toplevel, was_mapped;
+  
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
 
   if (GDK_WINDOW_DESTROYED (window) ||
       (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
-    {
-      return;
-    }
+    return;
 
+  if (!new_parent)
+    new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
+  
   private = (GdkWindowObject *) window;
+  new_parent_private = (GdkWindowObject *)new_parent;
+
+  /* No input-output children of input-only windows */
+  if (new_parent_private->input_only && !private->input_only)
+    return;
+
+  /* Don't create loops in hierarchy */
+  if (is_parent_of (window, new_parent))
+    return;
+  
+  if (private->cairo_surface)
+    {
+      /* This might be wrong in the new parent, e.g. for non-native surfaces.
+        To make sure we're ok, just wipe it. */
+      cairo_surface_finish (private->cairo_surface);
+      cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+                                  NULL, NULL);
+    }
+  
+  old_parent = private->parent;
 
   /* Break up redirection if inherited */
   if (private->redirect && private->redirect->redirected != private)
@@ -428,39 +910,182 @@ gdk_window_reparent (GdkWindow *window,
       remove_redirect_from_children (private, private->redirect);
       private->redirect = NULL;
     }
-  
-  show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
 
-  /* Inherit parent redirect if we don't have our own */
-  if (private->parent && private->redirect == NULL)
+  was_toplevel = private->parent == NULL;
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
+  show = FALSE;
+  
+  if (gdk_window_has_impl (private))
     {
-      private->redirect = private->parent->redirect;
-      apply_redirect_to_children (private, private->redirect);
+      /* Native window */
+      show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
     }
+  else
+    {
+      if (new_parent_private->window_type == GDK_WINDOW_ROOT)
+       {
+         /* TODO: We need to convert to a native window here */
+         g_warning ("Reparenting client side windows to the root window not yet supported");
+         return;
+       }
 
-  if (show)
-    gdk_window_show (window);
-}
+      show = was_mapped;
+      gdk_window_hide (window);
 
-static void
-window_remove_filters (GdkWindow *window)
-{
-  GdkWindowObject *obj = (GdkWindowObject*) window;
+      change_impl (private, new_parent_private->impl);
+    }
 
-  if (obj->filters)
+  /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
+   * the root window
+   */
+  if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
     {
-      GList *tmp_list;
-      
-      for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
-       g_free (tmp_list->data);
-    
-      g_list_free (obj->filters);
-      obj->filters = NULL;
+      new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
+      new_parent_private = (GdkWindowObject *)new_parent;
     }
-}
 
-/**
- * _gdk_window_destroy_hierarchy:
+  private->parent = new_parent_private;
+  private->x = x;
+  private->y = y;
+
+  if (private->parent)
+    private->parent->children = g_list_remove (private->parent->children, window);
+  
+  new_parent_private->children = g_list_prepend (new_parent_private->children, window);
+  
+  /* Switch the window type as appropriate */
+
+  switch (GDK_WINDOW_TYPE (new_parent))
+    {
+    case GDK_WINDOW_ROOT:
+    case GDK_WINDOW_FOREIGN:
+      if (private->toplevel_window_type != -1)
+       GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
+      else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+       GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+      break;
+    case GDK_WINDOW_OFFSCREEN:
+    case GDK_WINDOW_TOPLEVEL:
+    case GDK_WINDOW_CHILD:
+    case GDK_WINDOW_DIALOG:
+    case GDK_WINDOW_TEMP:
+      if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
+       {
+         /* Save the original window type so we can restore it if the
+          * window is reparented back to be a toplevel
+          */
+         private->toplevel_window_type = GDK_WINDOW_TYPE (window);
+         GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
+       }
+    }
+
+  /* Inherit parent redirect if we don't have our own */
+  if (private->parent && private->redirect == NULL)
+    {
+      private->redirect = private->parent->redirect;
+      apply_redirect_to_children (private, private->redirect);
+    }
+
+  recompute_visible_regions (private, TRUE, FALSE);
+  if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
+    recompute_visible_regions (old_parent, FALSE, TRUE);
+  
+  if (show)
+    gdk_window_show_unraised (window);
+  else
+    _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+/**
+ * gdk_window_set_has_native:
+ * @window: a #GdkWindow
+ * @has_native: whethe the window should have a native window
+ *
+ * Tries to create or remove a window-system native window for this
+ * GdkWindow. This may fail in some situations. For instance:
+ *
+ * Toplevel and foreign windows must have a native window.
+ * Offscreen window and children of them can never have native windows.
+ * Some backends may not support native child windows.
+ * 
+ **/
+void
+gdk_window_set_has_native (GdkWindow *window, gboolean has_native)
+{
+  GdkWindowObject *private;
+  GdkWindowObject *impl_window;
+  GdkDrawable *new_impl, *old_impl;
+  GdkScreen *screen;
+  GdkVisual *visual;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  private = (GdkWindowObject *) window;
+  
+  if (has_native)
+    {
+      /* Create native window */
+
+      if (gdk_window_has_impl (private))
+       /* Already has an impl, either native (ok) or
+          offscreen (not supported). Bail. */
+       return; 
+
+      impl_window = gdk_window_get_impl_window (private);
+      if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
+       return; /* native in offscreens not supported */
+
+      screen = gdk_drawable_get_screen (window);
+      visual = gdk_drawable_get_visual (window);
+
+      old_impl = private->impl;
+      _gdk_window_impl_new (window, screen, visual, GDK_EXPOSURE_MASK, NULL, 0);
+      new_impl = private->impl;
+      
+      private->impl = old_impl;
+      change_impl (private, new_impl);
+    }
+  else
+    {
+      /* Remove native window */
+
+      if (!gdk_window_has_impl (private))
+       return;  /* Not native, can't remove */
+
+      if (private->window_type == GDK_WINDOW_OFFSCREEN)
+       return; /* Not native, can't remove */
+      
+      if (private->parent == NULL ||
+         GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+       return; /* toplevel, must be native */
+      
+      /* TODO: remove native */
+    }
+}
+
+static void
+window_remove_filters (GdkWindow *window)
+{
+  GdkWindowObject *obj = (GdkWindowObject*) window;
+
+  if (obj->filters)
+    {
+      GList *tmp_list;
+      
+      for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
+       g_free (tmp_list->data);
+    
+      g_list_free (obj->filters);
+      obj->filters = NULL;
+    }
+}
+
+/**
+ * _gdk_window_destroy_hierarchy:
  * @window: a #GdkWindow
  * @recursing: If TRUE, then this is being called because a parent
  *            was destroyed. This generally means that the call to the 
@@ -513,6 +1138,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
     case GDK_WINDOW_DIALOG:
     case GDK_WINDOW_TEMP:
     case GDK_WINDOW_FOREIGN:
+    case GDK_WINDOW_OFFSCREEN:
       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
        {
          /* Logically, it probably makes more sense to send
@@ -533,8 +1159,6 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
        }
       else
        {
-         private->state |= GDK_WINDOW_STATE_WITHDRAWN;
-         
          if (private->parent)
            {
              GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
@@ -542,7 +1166,6 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
                parent_private->children = g_list_remove (parent_private->children, window);
            }
 
-         _gdk_window_clear_update_area (window);
          gdk_window_free_paint_stack (window);
          
          if (private->bg_pixmap &&
@@ -573,8 +1196,32 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
              
              g_list_free (children);
            }
+
+         _gdk_window_clear_update_area (window); 
          
-         _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
+         if (private->cairo_surface)
+           {
+             cairo_surface_finish (private->cairo_surface);
+             cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+                                          NULL, NULL);
+           }
+
+         if (gdk_window_has_impl (private))
+           {
+             if (gdk_window_is_offscreen (private))
+               _gdk_offscreen_window_destroy (window, recursing);
+             else
+               _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
+           }
+         else
+           {
+             /* hide to make sure we repaint and break grabs */
+             gdk_window_hide (window);
+             /* NULL out impl so we don't double free it on finalize */
+             private->impl = NULL;
+           }
+
+         private->state |= GDK_WINDOW_STATE_WITHDRAWN;
          private->parent = NULL;
          private->destroyed = TRUE;
 
@@ -1036,6 +1683,119 @@ gdk_window_get_state (GdkWindow *window)
   return private->state;
 }
 
+
+/* This creates an empty "implicit" paint region for the impl window.
+ * By itself this does nothing, but real paints to this window
+ * or children of it can use this pixmap as backing to avoid allocating
+ * multiple pixmaps for subwindow rendering. When doing so they
+ * add to the region of the implicit paint region, which will be
+ * pushed to the window when the implicit paint region is ended.
+ * Such paints should not copy anything to the window on paint end, but
+ * should rely on the implicit paint end.
+ * The implicit paint will be automatically ended if someone draws
+ * directly to the window or a child window.
+ */
+static gboolean
+gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowPaint *paint;
+
+  g_assert (gdk_window_has_impl (private));
+
+  if (GDK_IS_PAINTABLE (private->impl))
+    return FALSE; /* Implementation does double buffering */
+  
+  if (private->paint_stack != NULL ||
+      private->implicit_paint != NULL)
+    return FALSE; /* Don't stack implicit paints */
+
+  paint = g_new (GdkWindowPaint, 1);
+  paint->region = gdk_region_new (); /* Empty */
+  paint->x_offset = rect->x;
+  paint->y_offset = rect->y;
+  paint->uses_implicit = FALSE;
+  paint->surface = NULL;
+  paint->pixmap =
+    gdk_pixmap_new (window,
+                   MAX (rect->width, 1), MAX (rect->height, 1), -1);
+
+  private->implicit_paint = paint;
+  
+  return TRUE;
+}
+
+/* Ensure that all content related to this (sub)window is pushed to the
+   native region */
+static void
+gdk_window_flush_implicit_paint (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
+  GdkWindowPaint *paint;
+  GdkRegion *region;
+  GdkGC *tmp_gc;
+
+  /* Ensure that there is no explicit paint region. */
+  g_assert (private->paint_stack == NULL);
+  
+  impl_window = gdk_window_get_impl_window (private);
+  if (impl_window->implicit_paint == NULL)
+    return;
+
+  paint = impl_window->implicit_paint;
+  region = gdk_region_copy (private->clip_region_with_children);
+  gdk_region_offset (region, private->abs_x, private->abs_y);
+  gdk_region_intersect (region, paint->region);
+  
+  if (!gdk_region_empty (region))
+    {
+      /* Some regions are valid, push these to window now */
+      tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
+      _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
+      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+                        0, 0, paint->x_offset, paint->y_offset, -1, -1);
+      /* Reset clip region of the cached GdkGC */
+      gdk_gc_set_clip_region (tmp_gc, NULL);
+
+      /* Remove flushed region from the implicit paint */
+      gdk_region_subtract (paint->region, region);
+    }
+  else
+    gdk_region_destroy (region);
+}
+
+/* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
+static void
+gdk_window_end_implicit_paint (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowPaint *paint;
+  GdkGC *tmp_gc;
+
+  g_assert (gdk_window_has_impl (private));
+
+  g_assert (private->implicit_paint != NULL);
+
+  paint = private->implicit_paint;
+
+  private->implicit_paint = NULL;
+  
+  if (!gdk_region_empty (paint->region))
+    {
+      /* Some regions are valid, push these to window now */
+      tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
+      _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
+      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+                        0, 0, paint->x_offset, paint->y_offset, -1, -1);
+      /* Reset clip region of the cached GdkGC */
+      gdk_gc_set_clip_region (tmp_gc, NULL);
+    }
+  
+  g_object_unref (paint->pixmap);
+  g_free (paint);
+}
+
 /**
  * gdk_window_begin_paint_rect:
  * @window: a #GdkWindow
@@ -1115,7 +1875,8 @@ gdk_window_begin_paint_region (GdkWindow       *window,
 #ifdef USE_BACKING_STORE
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkRectangle clip_box;
-  GdkWindowPaint *paint;
+  GdkWindowPaint *paint, *implicit_paint;
+  GdkWindowObject *impl_window;
   GSList *list;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
@@ -1129,24 +1890,59 @@ gdk_window_begin_paint_region (GdkWindow       *window,
 
       if (iface->begin_paint_region)
         iface->begin_paint_region ((GdkPaintable*)private->impl, region);
-
+      
       return;
     }
 
   gdk_region_get_clipbox (region, &clip_box);
 
+  impl_window = gdk_window_get_impl_window (private);
+  implicit_paint = impl_window->implicit_paint;
+
   paint = g_new (GdkWindowPaint, 1);
-  paint->region = gdk_region_copy (region);
-  paint->x_offset = clip_box.x;
-  paint->y_offset = clip_box.y;
-  paint->pixmap =
-    gdk_pixmap_new (window,
-                   MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
+  if (implicit_paint)
+    {
+      int width, height;
 
-  paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
-  cairo_surface_set_device_offset (paint->surface,
-                                  - paint->x_offset, - paint->y_offset);
+      paint->uses_implicit = TRUE;
+      paint->pixmap = g_object_ref (implicit_paint->pixmap);
+      paint->x_offset = -private->abs_x + implicit_paint->x_offset;
+      paint->y_offset = -private->abs_y + implicit_paint->y_offset;
+      paint->region = gdk_region_copy (region);
+      gdk_region_intersect (paint->region, private->clip_region_with_children);
+
+      /* It would be nice if we had some cairo support here so we
+        could set the clip rect on the cairo surface */
+      width = private->abs_x + private->width;
+      height = private->abs_y + private->height;
+      
+      paint->surface = _gdk_windowing_create_cairo_surface (((GdkPixmapObject *)paint->pixmap)->impl,
+                                                           width, height);
+      if (paint->surface)
+       cairo_surface_set_device_offset (paint->surface,
+                                        - paint->x_offset, - paint->y_offset);
+
+      /* Mark the region as valid on the implicit paint */
+      gdk_region_offset (paint->region, private->abs_x, private->abs_y); 
+      gdk_region_union (implicit_paint->region, paint->region);
+      gdk_region_offset (paint->region, -private->abs_x, -private->abs_y); 
+    }
+  else
+    {
+      paint->uses_implicit = FALSE;
+      paint->region = gdk_region_copy (region);
+      paint->x_offset = clip_box.x;
+      paint->y_offset = clip_box.y;
+      paint->pixmap =
+       gdk_pixmap_new (window,
+                       MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
+
+      paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
+      cairo_surface_set_device_offset (paint->surface,
+                                      - paint->x_offset, - paint->y_offset);
+    }
   
+      
   for (list = private->paint_stack; list != NULL; list = list->next)
     {
       GdkWindowPaint *tmp_paint = list->data;
@@ -1156,7 +1952,7 @@ gdk_window_begin_paint_region (GdkWindow       *window,
   
   private->paint_stack = g_slist_prepend (private->paint_stack, paint);
 
-  if (!gdk_region_empty (region))
+  if (!gdk_region_empty (paint->region))
     {
       gdk_window_clear_backing_rect (window,
                                     clip_box.x, clip_box.y,
@@ -1165,6 +1961,55 @@ gdk_window_begin_paint_region (GdkWindow       *window,
 #endif /* USE_BACKING_STORE */
 }
 
+static void
+setup_redirect_clip (GdkWindow      *window,
+                    GdkGC          *gc,
+                    int            *x_offset_out,
+                    int            *y_offset_out)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkRegion *visible_region;
+  GdkRectangle dest_rect;
+  GdkRegion *tmpreg;
+  GdkWindow *toplevel;
+  int x_offset, y_offset;
+
+  toplevel = GDK_WINDOW (private->redirect->redirected);
+  
+  /* Get the clip region for gc clip rect + window hierarchy in
+     window relative coords */
+  visible_region =
+    _gdk_window_calculate_full_clip_region (window, toplevel,
+                                           TRUE,
+                                           &x_offset, 
+                                           &y_offset);
+
+  /* Compensate for the source pos/size */
+  x_offset -= private->redirect->src_x;
+  y_offset -= private->redirect->src_y;
+  dest_rect.x = -x_offset;
+  dest_rect.y = -y_offset;
+  dest_rect.width = private->redirect->width;
+  dest_rect.height = private->redirect->height;
+  tmpreg = gdk_region_rectangle (&dest_rect);
+  gdk_region_intersect (visible_region, tmpreg);
+  gdk_region_destroy (tmpreg);
+
+  /* Compensate for the dest pos */
+  x_offset += private->redirect->dest_x;
+  y_offset += private->redirect->dest_y;
+
+  gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
+
+  /* offset clip and tiles from window coords to pixmaps coords */
+  gdk_gc_offset (gc, -x_offset, -y_offset);
+
+  gdk_region_destroy (visible_region);
+
+  *x_offset_out = x_offset;
+  *y_offset_out = y_offset;
+}
+
 /**
  * gdk_window_end_paint:
  * @window: a #GdkWindow
@@ -1188,6 +2033,7 @@ gdk_window_end_paint (GdkWindow *window)
   GdkGC *tmp_gc;
   GdkRectangle clip_box;
   gint x_offset, y_offset;
+  GdkRegion *full_clip;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -1210,36 +2056,42 @@ gdk_window_end_paint (GdkWindow *window)
     }
 
   paint = private->paint_stack->data;
+
   private->paint_stack = g_slist_delete_link (private->paint_stack, 
-                                              private->paint_stack);
+                                             private->paint_stack);
 
   gdk_region_get_clipbox (paint->region, &clip_box);
 
   tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, &x_offset, &y_offset);
-
-  gdk_gc_set_clip_region (tmp_gc, paint->region);
-  gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
-
-  gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
-                     clip_box.x - paint->x_offset,
-                     clip_box.y - paint->y_offset,
-                     clip_box.x - x_offset, clip_box.y - y_offset,
-                     clip_box.width, clip_box.height);
+  x_offset = -private->abs_x;
+  y_offset = -private->abs_y;
 
+  if (!paint->uses_implicit)
+    {
+      full_clip = gdk_region_copy (private->clip_region_with_children);
+      gdk_region_intersect (full_clip, paint->region);
+      _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
+      gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
+      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+                        clip_box.x - paint->x_offset,
+                        clip_box.y - paint->y_offset,
+                        clip_box.x - x_offset, clip_box.y - y_offset,
+                        clip_box.width, clip_box.height);
+    }
+  
   if (private->redirect)
     {
-      GdkWindowClipData data;
-      
-      setup_redirect_clip (window, tmp_gc, &data);
+      int x_offset, y_offset;
+
+      /* TODO: Should also use paint->region for clipping */
+      setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
       gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
                         clip_box.x - paint->x_offset,
                         clip_box.y - paint->y_offset,
-                        clip_box.x + data.x_offset,
-                        clip_box.y + data.y_offset,
+                        clip_box.x + x_offset,
+                        clip_box.y + y_offset,
                         clip_box.width, clip_box.height);
-      reset_redirect_clip (window, tmp_gc, &data);
     }
   
   /* Reset clip region of the cached GdkGC */
@@ -1321,7 +2173,10 @@ gdk_window_get_offsets (GdkWindow *window,
       *y_offset = paint->y_offset;
     }
   else
-    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, x_offset, y_offset);
+    {
+      *x_offset = -private->abs_x;
+      *y_offset = -private->abs_y;
+    }
 }
 
 /**
@@ -1380,6 +2235,48 @@ gdk_window_get_internal_paint_info (GdkWindow    *window,
     *y_offset = y_off;
 }
 
+static void
+setup_clip_for_draw (GdkDrawable *drawable,
+                    GdkGC *gc,
+                    int old_clip_x, int old_clip_y,
+                    GdkRegion **old_clip_region)
+{
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
+  GdkRegion *clip;
+
+  if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
+    clip = gdk_region_copy (private->clip_region_with_children);
+  else
+    clip = gdk_region_copy (private->clip_region);
+    
+  /* There was a clip origin set appart from the window offset,
+     need to take this into consideration */
+  if (old_clip_x != 0 || old_clip_y != 0)
+    gdk_region_offset (clip, -old_clip_x, -old_clip_y);
+
+  _gdk_gc_intersect_clip_region (gc, clip, old_clip_region);
+}
+
+static void
+setup_clip_for_paint (GdkDrawable *drawable,
+                     GdkWindowPaint *paint,
+                     GdkGC *gc,
+                     int old_clip_x, int old_clip_y,
+                     GdkRegion **old_clip_region)
+{
+  GdkRegion *clip;
+
+  clip = gdk_region_copy (paint->region);
+  
+  /* There was a clip origin set appart from the window offset,
+     need to take this into consideration */
+  if (old_clip_x != 0 || old_clip_y != 0)
+    gdk_region_offset (clip, -old_clip_x, -old_clip_y);
+
+  _gdk_gc_intersect_clip_region (gc, clip, old_clip_region);
+}
+
+
 #define OFFSET_GC(gc)                                         \
     gint x_offset, y_offset;                                 \
     gint old_clip_x = gc->clip_x_origin;    \
@@ -1402,6 +2299,25 @@ gdk_window_get_internal_paint_info (GdkWindow    *window,
        gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y);       \
      }
 
+#define SETUP_PAINT_GC_CLIP(gc)                             \
+      GdkRegion *old_clip_region;                           \
+      if (paint->uses_implicit)                                    \
+       setup_clip_for_paint (drawable, paint, gc, old_clip_x,  \
+                              old_clip_y, &old_clip_region);
+
+#define RESTORE_PAINT_GC_CLIP(gc)                          \
+      if (paint->uses_implicit)                           \
+        _gdk_gc_set_clip_region_internal (gc, old_clip_region, FALSE);
+
+
+#define SETUP_DIRECT_GC_CLIP(gc)                            \
+      GdkRegion *old_clip_region;                           \
+      gdk_window_flush_implicit_paint ((GdkWindow *)drawable);\
+      setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y, &old_clip_region);
+
+#define RESTORE_DIRECT_GC_CLIP(gc)                                 \
+      _gdk_gc_set_clip_region_internal (gc, old_clip_region, FALSE);
+
 static GdkGC *
 gdk_window_create_gc (GdkDrawable     *drawable,
                       GdkGCValues     *values,
@@ -1434,12 +2350,18 @@ gdk_window_draw_rectangle (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_rectangle (paint->pixmap, gc, filled,
                           x - x_offset, y - y_offset, width, height);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_rectangle (private->impl, gc, filled,
-                        x - x_offset, y - y_offset, width, height);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_rectangle (private->impl, gc, filled,
+                         x - x_offset, y - y_offset, width, height);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -1464,14 +2386,20 @@ gdk_window_draw_arc (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_arc (paint->pixmap, gc, filled,
                    x - x_offset, y - y_offset,
                    width, height, angle1, angle2);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_arc (private->impl, gc, filled,
-                  x - x_offset, y - y_offset,
-                  width, height, angle1, angle2);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_arc (private->impl, gc, filled,
+                   x - x_offset, y - y_offset,
+                   width, height, angle1, angle2);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   RESTORE_GC (gc);
 }
 
@@ -1507,11 +2435,16 @@ gdk_window_draw_polygon (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_polygon (paint->pixmap, gc, filled, new_points, npoints);
-
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   
   if (new_points != points)
     g_free (new_points);
@@ -1537,13 +2470,19 @@ gdk_window_draw_text (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_text (paint->pixmap, font, gc, 
                     x - x_offset, y - y_offset, text, text_length);
 
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_text (private->impl, font, gc,
-                   x - x_offset, y - y_offset, text, text_length);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_text (private->impl, font, gc,
+                    x - x_offset, y - y_offset, text, text_length);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -1566,17 +2505,36 @@ gdk_window_draw_text_wc (GdkDrawable    *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_text_wc (paint->pixmap, font, gc, 
                        x - x_offset, y - y_offset, text, text_length);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_text_wc (private->impl, font, gc,
-                      x - x_offset, y - y_offset, text, text_length);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_text_wc (private->impl, font, gc,
+                       x - x_offset, y - y_offset, text, text_length);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   
   RESTORE_GC (gc);
 }
 
-static GdkDrawable*
+static GdkDrawable *
+gdk_window_get_source_drawable (GdkDrawable *drawable)
+{
+  GdkWindow *window = GDK_WINDOW (drawable);
+  GdkWindowObject *private;
+
+  private = (GdkWindowObject *) window;
+  if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
+    return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
+  
+  return drawable;
+}
+
+static GdkDrawable *
 gdk_window_get_composite_drawable (GdkDrawable *drawable,
                                    gint         x,
                                    gint         y,
@@ -1591,19 +2549,17 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable,
   GdkRectangle rect;
   GdkGC *tmp_gc;
   gboolean overlap_buffer;
+  GdkDrawable *source;
+  GdkWindowObject *impl_window;
+  GdkWindowPaint *implicit_paint;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (GDK_WINDOW (drawable),
-                                                          composite_x_offset,
-                                                          composite_y_offset);
-  
-  if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
-      || private->paint_stack == NULL)
-    {
-      /* No backing store */
-      return g_object_ref (drawable);
-    }
+  *composite_x_offset = -private->abs_x;
+  *composite_y_offset = -private->abs_y;
 
-  /* See if the buffered part is overlapping the part we want
+  if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
+    return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
+
+  /* See if any buffered part is overlapping the part we want
    * to get
    */
   rect.x = x;
@@ -1612,14 +2568,14 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable,
   rect.height = height;
 
   overlap_buffer = FALSE;
-  
+
   for (list = private->paint_stack; list != NULL; list = list->next)
     {
       GdkWindowPaint *paint = list->data;
       GdkOverlapType overlap;
-
+      
       overlap = gdk_region_rect_in (paint->region, &rect);
-
+      
       if (overlap == GDK_OVERLAP_RECTANGLE_IN)
        {
          *composite_x_offset = paint->x_offset;
@@ -1634,26 +2590,65 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable,
        }
     }
 
-  if (!overlap_buffer)
-    return g_object_ref (drawable);
+  impl_window = gdk_window_get_impl_window (private);
+  implicit_paint = impl_window->implicit_paint;
+  if (implicit_paint)
+    {
+      GdkOverlapType overlap;
+
+      rect.x += private->abs_x;
+      rect.y += private->abs_y;
+      
+      overlap = gdk_region_rect_in (implicit_paint->region, &rect);
+      if (overlap == GDK_OVERLAP_RECTANGLE_IN)
+       {
+         *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
+         *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
+         
+         return g_object_ref (implicit_paint->pixmap);
+       }
+      else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
+       overlap_buffer = TRUE;
+    }
 
+  if (!overlap_buffer)
+    return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
+  
   tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
   tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
 
+  source = _gdk_drawable_get_source_drawable (drawable);
+  
   /* Copy the current window contents */
   gdk_draw_drawable (tmp_pixmap,
                      tmp_gc,
-                     private->impl,
+                     GDK_WINDOW_OBJECT (source)->impl,
                      x - *composite_x_offset,
                      y - *composite_y_offset,
                      0, 0,
                      width, height);
 
   /* paint the backing stores */
+  if (implicit_paint)
+    {
+      GdkWindowPaint *paint = list->data;
+      
+      gdk_gc_set_clip_region (tmp_gc, paint->region);
+      gdk_gc_set_clip_origin (tmp_gc, -x  - paint->x_offset, -y  - paint->y_offset);
+      
+      gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
+                        x - paint->x_offset,
+                        y - paint->y_offset,
+                        0, 0, width, height);
+    }
+  
   for (list = private->paint_stack; list != NULL; list = list->next)
     {
       GdkWindowPaint *paint = list->data;
 
+      if (paint->uses_implicit)
+       continue; /* We already copied this above */
+      
       gdk_gc_set_clip_region (tmp_gc, paint->region);
       gdk_gc_set_clip_origin (tmp_gc, -x, -y);
       
@@ -1662,7 +2657,7 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable,
                         y - paint->y_offset,
                         0, 0, width, height);
     }
-
+  
   /* Reset clip region of the cached GdkGC */
   gdk_gc_set_clip_region (tmp_gc, NULL);
 
@@ -1679,7 +2674,7 @@ gdk_window_get_clip_region (GdkDrawable *drawable)
   GdkWindowObject *private = (GdkWindowObject *)drawable;
   GdkRegion *result;
 
-  result = gdk_drawable_get_clip_region (private->impl);
+  result = gdk_region_copy (private->clip_region);
 
   if (private->paint_stack)
     {
@@ -1706,8 +2701,8 @@ static GdkRegion*
 gdk_window_get_visible_region (GdkDrawable *drawable)
 {
   GdkWindowObject *private = (GdkWindowObject*) drawable;
-  
-  return gdk_drawable_get_visible_region (private->impl);
+
+  return gdk_region_copy (private->clip_region);
 }
 
 static void
@@ -1731,16 +2726,22 @@ gdk_window_draw_drawable (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_drawable (paint->pixmap, gc,
                          src, xsrc, ysrc,
                         xdest - x_offset, ydest - y_offset, width, height);
 
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_drawable (private->impl, gc,
-                       src, xsrc, ysrc,
-                       xdest - x_offset, ydest - y_offset,
-                       width, height);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_drawable (private->impl, gc,
+                        src, xsrc, ysrc,
+                        xdest - x_offset, ydest - y_offset,
+                        width, height);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -1776,10 +2777,16 @@ gdk_window_draw_points (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_points (paint->pixmap, gc, new_points, npoints);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_points (private->impl, gc, points, npoints);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_points (private->impl, gc, points, npoints);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   if (new_points != points)
     g_free (new_points);
@@ -1820,10 +2827,16 @@ gdk_window_draw_segments (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_segments (paint->pixmap, gc, new_segs, nsegs);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_segments (private->impl, gc, new_segs, nsegs);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_segments (private->impl, gc, new_segs, nsegs);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   
   if (new_segs != segs)
     g_free (new_segs);
@@ -1862,10 +2875,16 @@ gdk_window_draw_lines (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_lines (paint->pixmap, gc, new_points, npoints);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_lines (private->impl, gc, new_points, npoints);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_lines (private->impl, gc, new_points, npoints);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   if (new_points != points)
     g_free (new_points);
@@ -1892,11 +2911,17 @@ gdk_window_draw_glyphs (GdkDrawable      *drawable,
     {
       GdkWindowPaint *paint = private->paint_stack->data;
 
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_glyphs (paint->pixmap, gc, font, x - x_offset, y - y_offset, glyphs);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_glyphs (private->impl, gc, font,
-                     x - x_offset, y - y_offset, glyphs);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_glyphs (private->impl, gc, font,
+                      x - x_offset, y - y_offset, glyphs);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -1947,10 +2972,16 @@ gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
     {
       GdkWindowPaint *paint = private->paint_stack->data;
 
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_glyphs_transformed (paint->pixmap, gc, matrix, font, x, y, glyphs);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -2116,16 +3147,16 @@ gdk_window_clear_backing_rect_redirect (GdkWindow *window,
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
+  clip_region = _gdk_window_calculate_full_clip_region (window,
+                                                       GDK_WINDOW (redirect->redirected),
+                                                       TRUE,
+                                                       &x_offset, &y_offset);
+  
   paint.x_offset = x_offset;
   paint.y_offset = y_offset;
   paint.pixmap = redirect->pixmap;
   paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
   
-  clip_region = _gdk_window_calculate_full_clip_region (window,
-                                                       GDK_WINDOW (redirect->redirected),
-                                                       NULL, TRUE,
-                                                       &x_offset, &y_offset);
-  
   method.cr = NULL;
   method.gc = NULL;
   setup_backing_rect_method (&method, window, &paint, 0, 0);
@@ -2156,6 +3187,54 @@ gdk_window_clear_backing_rect_redirect (GdkWindow *window,
   cairo_surface_destroy (paint.surface);
 }
 
+static void
+gdk_window_clear_backing_rect_direct (GdkWindow *window,
+                                     gint       x,
+                                     gint       y,
+                                     gint       width,
+                                     gint       height)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  BackingRectMethod method;
+  GdkWindowPaint paint;
+  
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  paint.x_offset = 0;
+  paint.y_offset = 0;
+  paint.pixmap = window;
+  paint.surface = _gdk_drawable_ref_cairo_surface (window);
+  
+  method.cr = NULL;
+  method.gc = NULL;
+  setup_backing_rect_method (&method, window, &paint, 0, 0);
+
+  if (method.cr)
+    {
+      g_assert (method.gc == NULL);
+
+      gdk_cairo_region (method.cr, private->clip_region_with_children);
+      cairo_clip (method.cr);
+      
+      cairo_rectangle (method.cr, x, y, width, height);
+      cairo_fill (method.cr);
+
+      cairo_destroy (method.cr);
+    }
+  else
+    {
+      g_assert (method.gc != NULL);
+
+      gdk_gc_set_clip_region (method.gc, private->clip_region_with_children);
+      gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
+      g_object_unref (method.gc);
+
+    }
+
+  cairo_surface_destroy (paint.surface);
+}
+
 
 /**
  * gdk_window_clear:
@@ -2176,6 +3255,43 @@ gdk_window_clear (GdkWindow *window)
                          width, height);
 }
 
+static void
+gdk_window_clear_area_internal (GdkWindow *window,
+                               gint       x,
+                               gint       y,
+                               gint       width,
+                               gint       height,
+                               gboolean   send_expose)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (private->paint_stack)
+    gdk_window_clear_backing_rect (window, x, y, width, height);
+  else
+    {
+      if (private->redirect)
+       gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
+
+      
+      
+      gdk_window_clear_backing_rect_direct (window, x, y, width, height);
+      if (send_expose)
+       {
+         GdkRectangle rect;
+
+         rect.x = x;
+         rect.y = x;
+         rect.width = width;
+         rect.height = height;
+         
+         gdk_window_invalidate_rect (window, &rect, FALSE);
+       }
+    }
+}
+
+
 /**
  * gdk_window_clear_area:
  * @window: a #GdkWindow
@@ -2194,22 +3310,10 @@ gdk_window_clear_area (GdkWindow *window,
                       gint       width,
                       gint       height)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (private->paint_stack)
-    gdk_window_clear_backing_rect (window, x, y, width, height);
-  else
-    {
-      if (private->redirect)
-       gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
-
-      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
-                                                             x, y,
-                                                             width, height,
-                                                             FALSE);
-    }
+  gdk_window_clear_area_internal (window,
+                                 x, y,
+                                 width, height,
+                                 FALSE);
 }
 
 /**
@@ -2234,20 +3338,10 @@ gdk_window_clear_area_e (GdkWindow *window,
                         gint       width,
                         gint       height)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (private->paint_stack)
-    gdk_window_clear_backing_rect (window, x, y, width, height);
-
-  if (private->redirect)
-    gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
-                                                         x, y,
-                                                         width, height,
-                                                         TRUE);
+  gdk_window_clear_area_internal (window,
+                                 x, y,
+                                 width, height,
+                                 TRUE);
 }
 
 static void
@@ -2271,15 +3365,21 @@ gdk_window_draw_image (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_image (paint->pixmap, gc, image, xsrc, ysrc,
                       xdest - x_offset, ydest - y_offset,
                       width, height);
 
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
-                    xdest - x_offset, ydest - y_offset,
-                    width, height);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
+                     xdest - x_offset, ydest - y_offset,
+                     width, height);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -2310,16 +3410,22 @@ gdk_window_draw_pixbuf (GdkDrawable     *drawable,
       if (private->paint_stack)
        {
          GdkWindowPaint *paint = private->paint_stack->data;
+         SETUP_PAINT_GC_CLIP (gc);
          gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
                           dest_x - x_offset, dest_y - y_offset,
                           width, height,
                           dither, x_dither - x_offset, y_dither - y_offset);
+         RESTORE_PAINT_GC_CLIP (gc);
        }
       else
-       gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
-                        dest_x - x_offset, dest_y - y_offset,
-                        width, height,
-                        dither, x_dither, y_dither);
+       {
+         SETUP_DIRECT_GC_CLIP(gc);
+         gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
+                          dest_x - x_offset, dest_y - y_offset,
+                          width, height,
+                          dither, x_dither, y_dither);
+         RESTORE_DIRECT_GC_CLIP(gc);
+       }
       
       RESTORE_GC (gc);
     }
@@ -2331,16 +3437,20 @@ gdk_window_draw_pixbuf (GdkDrawable     *drawable,
       if (private->paint_stack)
        {
          GdkWindowPaint *paint = private->paint_stack->data;
+         /* TODO: Do paint clipping here... */
          gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
                           dest_x - x_offset, dest_y - y_offset,
                           width, height,
                            dither, x_dither - x_offset, y_dither - y_offset);
        }
       else
-       gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
-                        dest_x - x_offset, dest_y - y_offset,
-                        width, height,
-                        dither, x_dither, y_dither);
+       {
+         /* TODO: No GC passed in, but still want clipping here... */
+         gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
+                          dest_x - x_offset, dest_y - y_offset,
+                          width, height,
+                          dither, x_dither, y_dither);
+       }
     }
 }
 
@@ -2379,10 +3489,16 @@ gdk_window_draw_trapezoids (GdkDrawable   *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_trapezoids (paint->pixmap, gc, trapezoids, n_trapezoids);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   
   g_free (new_trapezoids);
 
@@ -2394,10 +3510,12 @@ gdk_window_real_get_size (GdkDrawable *drawable,
                           gint *width,
                           gint *height)
 {
-  g_return_if_fail (GDK_IS_WINDOW (drawable));
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
 
-  gdk_drawable_get_size (GDK_WINDOW_OBJECT (drawable)->impl,
-                         width, height);
+  if (width)
+    *width = private->width;
+  if (height)
+    *height = private->height;
 }
 
 static GdkVisual*
@@ -2469,9 +3587,10 @@ gdk_window_copy_to_image (GdkDrawable     *drawable,
   /* If we're here, a composite image was not necessary, so
    * we can ignore the paint stack.
    */
-  
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (drawable,
-                                                          &x_offset, &y_offset);
+
+  /* TODO: Is this right? */
+  x_offset = 0;
+  y_offset = 0; 
   
   return gdk_drawable_copy_to_image (private->impl,
                                     image,
@@ -2481,6 +3600,14 @@ gdk_window_copy_to_image (GdkDrawable     *drawable,
                                     width, height);
 }
 
+static void
+gdk_window_cairo_surface_destroy (void *data)
+{
+  GdkWindowObject *private = (GdkWindowObject*) data;
+
+  private->cairo_surface = NULL;
+}
+
 static cairo_surface_t *
 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
 {
@@ -2495,17 +3622,185 @@ gdk_window_ref_cairo_surface (GdkDrawable *drawable)
       cairo_surface_reference (surface);
     }
   else
-    surface = _gdk_drawable_ref_cairo_surface (private->impl);
+    {
+      
+      /* This will be drawing directly to the window, so flush implicit paint */
+      gdk_window_flush_implicit_paint ((GdkWindow *)drawable);
+      
+      if (!private->cairo_surface)
+       {
+         int width, height;
+         GdkDrawable *source;
+
+         /* It would be nice if we had some cairo support here so we
+            could set the clip rect on the cairo surface */
+         width = private->abs_x + private->width;
+         height = private->abs_y + private->height;
+
+         source = _gdk_drawable_get_source_drawable (drawable);
+
+         /* TODO: Avoid the typecheck crap by adding virtual call */
+         private->cairo_surface = _gdk_windowing_create_cairo_surface (GDK_IS_PIXMAP (source) ? GDK_PIXMAP_OBJECT(source)->impl : GDK_WINDOW_OBJECT(source)->impl,
+                                                                       width, height);
+         
+         if (private->cairo_surface)
+           {
+             cairo_surface_set_device_offset (private->cairo_surface, 
+                                              private->abs_x,
+                                              private->abs_y);
+             
+             cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+                                          drawable, gdk_window_cairo_surface_destroy);
+           }
+       }
+      else
+       cairo_surface_reference (private->cairo_surface);
+      
+      surface = private->cairo_surface;
+    }
 
   return surface;
 }
 
+static void
+gdk_window_set_cairo_clip (GdkDrawable *drawable,
+                          cairo_t *cr)
+{
+  GdkWindowObject *private = (GdkWindowObject*) drawable;
+
+  if (!private->paint_stack)
+    {
+      cairo_save (cr);
+      cairo_identity_matrix (cr);
+      
+      cairo_new_path (cr);
+      gdk_cairo_region (cr, private->clip_region);
+      
+      cairo_restore (cr);
+      cairo_clip (cr);
+    }
+  else
+    {
+      GdkWindowPaint *paint = private->paint_stack->data;
+
+      /* Only needs to clip to region if piggybacking
+        on an implicit paint pixmap */
+      if (paint->uses_implicit)
+       {
+         cairo_save (cr);
+         cairo_identity_matrix (cr);
+         
+         cairo_new_path (cr);
+         gdk_cairo_region (cr, paint->region);
+         cairo_restore (cr);
+         
+         cairo_clip (cr);
+       }
+    }
+}
+
 /* Code for dirty-region queueing
  */
 static GSList *update_windows = NULL;
 static guint update_idle = 0;
 static gboolean debug_updates = FALSE;
 
+static inline gboolean
+gdk_window_is_ancestor (GdkWindow *window,
+                        GdkWindow *ancestor)
+{
+  while (window)
+    {
+      GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
+
+      if (parent == ancestor)
+        return TRUE;
+
+      window = parent;
+    }
+
+  return FALSE;
+}
+
+static void
+gdk_window_add_update_window (GdkWindow *window)
+{
+  GSList *tmp;
+  GSList *prev = NULL;
+  gboolean has_ancestor_in_list = FALSE;
+
+  for (tmp = update_windows; tmp; tmp = tmp->next)
+    {
+      GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
+
+      /*  check if tmp is an ancestor of "window"; if it is, set a
+       *  flag indicating that all following windows are either
+       *  children of "window" or from a differen hierarchy
+       */
+      if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
+        has_ancestor_in_list = TRUE;
+
+      /* insert in reverse stacking order when adding around siblings,
+       * so processing updates properly paints over lower stacked windows
+       */
+      if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
+        {
+          gint index = g_list_index (parent->children, window);
+          for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
+            {
+              gint sibling_index = g_list_index (parent->children, tmp->data);
+              if (index > sibling_index)
+                break;
+              prev = tmp;
+            }
+          /* here, tmp got advanced past all lower stacked siblings */
+          tmp = g_slist_prepend (tmp, window);
+          if (prev)
+            prev->next = tmp;
+          else
+            update_windows = tmp;
+          return;
+        }
+
+      /*  if "window" has an ancestor in the list and tmp is one of
+       *  "window's" children, insert "window" before tmp
+       */
+      if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
+        {
+          tmp = g_slist_prepend (tmp, window);
+
+          if (prev)
+            prev->next = tmp;
+          else
+            update_windows = tmp;
+          return;
+        }
+
+      /*  if we're at the end of the list and had an ancestor it it,
+       *  append to the list
+       */
+      if (! tmp->next && has_ancestor_in_list)
+        {
+          tmp = g_slist_append (tmp, window);
+          return;
+        }
+
+      prev = tmp;
+    }
+
+  /*  if all above checks failed ("window" is from a different
+   *  hierarchy than what is already in the list) or the list is
+   *  empty, prepend
+   */
+  update_windows = g_slist_prepend (update_windows, window);
+}
+
+static void
+gdk_window_remove_update_window (GdkWindow *window)
+{
+  update_windows = g_slist_remove (update_windows, window);
+}
+
 static gboolean
 gdk_window_update_idle (gpointer data)
 {
@@ -2539,11 +3834,78 @@ gdk_window_schedule_update (GdkWindow *window)
     }
 }
 
+static void
+gdk_window_process_updates_recurse (GdkWindow *window,
+                                   GdkRegion *expose_region)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *child;
+  GdkRegion *child_region;
+  GdkRectangle r;
+  GList *l;
+
+  if (gdk_region_empty (expose_region))
+    return;
+  
+  /* Iterate over children, starting at topmost */
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+      
+      if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
+       continue;
+
+      /* Ignore offscreen children, as they don't draw in their parent and
+       * don't take part in the clipping */
+      if (gdk_window_is_offscreen (child))
+       continue;
+
+      r.x = child->x;
+      r.y = child->y;
+      r.width = child->width;
+      r.height = child->height;
+      
+      child_region = gdk_region_rectangle (&r);
+      
+      if (child->impl == private->impl) 
+       {
+         /* Client side child, expose */
+         gdk_region_intersect (child_region, expose_region);
+         gdk_region_subtract (expose_region, child_region);
+         gdk_region_offset (child_region, -child->x, -child->y);
+         gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
+       }
+      else 
+       {
+         /* Native child, just remove area from expose region */
+         gdk_region_subtract (expose_region, child_region);
+       }
+      gdk_region_destroy (child_region);
+    }
+
+  if (private->event_mask & GDK_EXPOSURE_MASK)
+    {
+      GdkEvent event;
+      
+      event.expose.type = GDK_EXPOSE;
+      event.expose.window = g_object_ref (window);
+      event.expose.send_event = FALSE;
+      event.expose.count = 0;
+      event.expose.region = expose_region;
+      gdk_region_get_clipbox (expose_region, &event.expose.area);
+      
+      (*_gdk_event_func) (&event, _gdk_event_data);
+      
+      g_object_unref (window);
+    }
+}
+
 static void
 gdk_window_process_updates_internal (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   gboolean save_region = FALSE;
+  GdkRectangle clip_box;
 
   /* If an update got queued during update processing, we can get a
    * window in the update queue that has an empty update_area.
@@ -2559,7 +3921,7 @@ gdk_window_process_updates_internal (GdkWindow *window)
          GdkRectangle window_rect;
          GdkRegion *expose_region;
          GdkRegion *window_region;
-          gint width, height;
+         gboolean end_implicit;
 
           if (debug_updates)
             {
@@ -2567,43 +3929,29 @@ gdk_window_process_updates_internal (GdkWindow *window)
               gdk_display_sync (gdk_drawable_get_display (window));
               g_usleep (70000);
             }
-          
-         save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
 
+         save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
          if (save_region)
            expose_region = gdk_region_copy (update_area);
          else
            expose_region = update_area;
          
-          gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
-
          window_rect.x = 0;
          window_rect.y = 0;
-         window_rect.width = width;
-         window_rect.height = height;
+         window_rect.width = private->width;
+         window_rect.height = private->height;
 
          window_region = gdk_region_rectangle (&window_rect);
          gdk_region_intersect (expose_region,
                                window_region);
          gdk_region_destroy (window_region);
-         
-         if (!gdk_region_empty (expose_region) &&
-             (private->event_mask & GDK_EXPOSURE_MASK))
-           {
-             GdkEvent event;
-             
-             event.expose.type = GDK_EXPOSE;
-             event.expose.window = g_object_ref (window);
-             event.expose.send_event = FALSE;
-             event.expose.count = 0;
-             event.expose.region = expose_region;
-             gdk_region_get_clipbox (expose_region, &event.expose.area);
-             
-             (*_gdk_event_func) (&event, _gdk_event_data);
-             
-             g_object_unref (window);
-           }
 
+         gdk_region_get_clipbox (expose_region, &clip_box);
+         end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
+         gdk_window_process_updates_recurse (window, expose_region);
+         if (end_implicit)
+           gdk_window_end_implicit_paint (window);
+         
          if (expose_region != update_area)
            gdk_region_destroy (expose_region);
        }
@@ -2663,7 +4011,7 @@ gdk_window_process_all_updates (void)
         {
          if (private->update_freeze_count ||
              gdk_window_is_toplevel_frozen (tmp_list->data))
-           update_windows = g_slist_prepend (update_windows, private);
+           gdk_window_add_update_window ((GdkWindow *) private);
          else
            gdk_window_process_updates_internal (tmp_list->data);
        }
@@ -2697,6 +4045,7 @@ gdk_window_process_updates (GdkWindow *window,
                            gboolean   update_children)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -2709,23 +4058,24 @@ gdk_window_process_updates (GdkWindow *window,
 
       return;
     }
-  
-  if (private->update_area &&
-      !private->update_freeze_count &&
+
+  impl_window = gdk_window_get_impl_window (private);
+  if (impl_window->update_area &&
+      !impl_window->update_freeze_count &&
       !gdk_window_is_toplevel_frozen (window))
     {      
-      gdk_window_process_updates_internal (window);
-      update_windows = g_slist_remove (update_windows, window);
+      gdk_window_process_updates_internal ((GdkWindow *)impl_window);
+      gdk_window_remove_update_window ((GdkWindow *)impl_window);
     }
 
   if (update_children)
     {
-      GList *tmp_list = private->children;
-      while (tmp_list)
-       {
-         gdk_window_process_updates (tmp_list->data, TRUE);
-         tmp_list = tmp_list->next;
-       }
+      /* process updates in reverse stacking order so composition or
+       * painting over achieves the desired effect for offscreen windows
+       */
+      GList *node;
+      for (node = g_list_last (private->children); node; node = node->prev)
+        gdk_window_process_updates (node->data, TRUE);
     }
 }
 
@@ -2829,6 +4179,7 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
                                     gpointer   user_data)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
   GdkRegion *visible_region;
   GList *tmp_list;
 
@@ -2850,18 +4201,7 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
       return;
     }
 
-  /* windows that a redirection has ben setup for need to be considered
-   * fully visible, in order to avoid missing redirected paint ops
-   * anywhere in the window area.
-   */
-  if (private->redirect && private->redirect->redirected == private)
-    {
-      GdkRectangle visible_rect = { 0, 0, 0, 0 };
-      gdk_drawable_get_size (GDK_DRAWABLE (window), &visible_rect.width, &visible_rect.height);
-      visible_region = gdk_region_rectangle (&visible_rect);
-    }
-  else
-    visible_region = gdk_drawable_get_visible_region (window);
+  visible_region = gdk_drawable_get_visible_region (window);
   gdk_region_intersect (visible_region, region);
 
   tmp_list = private->children;
@@ -2873,17 +4213,17 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
        {
          GdkRegion *child_region;
          GdkRectangle child_rect;
-         
-         gdk_window_get_position ((GdkWindow *)child,
-                                  &child_rect.x, &child_rect.y);
-         gdk_drawable_get_size ((GdkDrawable *)child,
-                                &child_rect.width, &child_rect.height);
 
+         child_rect.x = child->x;
+         child_rect.y = child->y;
+         child_rect.width = child->width;
+         child_rect.height = child->height;
          child_region = gdk_region_rectangle (&child_rect);
          
          /* remove child area from the invalid area of the parent */
          if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
-             !child->composited)
+             !child->composited &&
+              !gdk_window_is_offscreen (child))
            gdk_region_subtract (visible_region, child_region);
          
          if (child_func && (*child_func) ((GdkWindow *)child, user_data))
@@ -2910,17 +4250,20 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
     {
       if (debug_updates)
         draw_ugly_color (window, region);
-
-      if (private->update_area)
+      
+      /* Convert to impl coords */
+      impl_window = gdk_window_get_impl_window (private);
+      gdk_region_offset (visible_region, private->abs_x, private->abs_y);
+      if (impl_window->update_area)
        {
-         gdk_region_union (private->update_area, visible_region);
+         gdk_region_union (impl_window->update_area, visible_region);
        }
       else
        {
-         update_windows = g_slist_prepend (update_windows, window);
-         private->update_area = gdk_region_copy (visible_region);
+         gdk_window_add_update_window ((GdkWindow *)impl_window);
+         impl_window->update_area = gdk_region_copy (visible_region);
          
-         gdk_window_schedule_update (window);
+         gdk_window_schedule_update ((GdkWindow *)impl_window);
        }
     }
   
@@ -2969,6 +4312,38 @@ gdk_window_invalidate_region (GdkWindow       *window,
                                       NULL);
 }
 
+/**
+ * _gdk_window_invalidate_for_expose:
+ * @window: a #GdkWindow
+ * @region: a #GdkRegion
+ *
+ * Adds @region to the update area for @window. The update area is the
+ * region that needs to be redrawn, or "dirty region." The call
+ * gdk_window_process_updates() sends one or more expose events to the
+ * window, which together cover the entire update area. An
+ * application would normally redraw the contents of @window in
+ * response to those expose events.
+ *
+ * GDK will call gdk_window_process_all_updates() on your behalf
+ * whenever your program returns to the main loop and becomes idle, so
+ * normally there's no need to do that manually, you just need to
+ * invalidate regions that you know should be redrawn.
+ *
+ * This version of invalidation is used when you recieve expose events
+ * from the native window system. It exposes the native window, plus
+ * any non-native child windows (but not native child windows, as those would
+ * have gotten their own expose events). 
+ **/
+void
+_gdk_window_invalidate_for_expose (GdkWindow       *window,
+                                  const GdkRegion *region)
+{
+  gdk_window_invalidate_maybe_recurse (window, region,
+                                      (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
+                                      NULL);
+}
+
+
 /**
  * gdk_window_get_update_area:
  * @window: a #GdkWindow
@@ -2986,18 +4361,42 @@ GdkRegion *
 gdk_window_get_update_area (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
   GdkRegion *tmp_region;
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-  if (private->update_area)
+  impl_window = gdk_window_get_impl_window (private);
+  
+  if (impl_window->update_area)
     {
-      tmp_region = private->update_area;
-      private->update_area = NULL;
+      tmp_region = gdk_region_copy (private->clip_region_with_children);
+      /* Convert to impl coords */
+      gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
+      gdk_region_intersect (tmp_region, impl_window->update_area);
 
-      update_windows = g_slist_remove (update_windows, window);
-      
-      return tmp_region;
+      if (gdk_region_empty (tmp_region))
+       {
+         gdk_region_destroy (tmp_region);
+         return NULL;
+       }
+      else
+       {
+         gdk_region_subtract (impl_window->update_area, tmp_region);
+
+         if (gdk_region_empty (impl_window->update_area))
+           {
+             gdk_region_destroy (impl_window->update_area);
+             impl_window->update_area = NULL;
+         
+             gdk_window_remove_update_window ((GdkWindow *)impl_window);
+           }
+         
+         /* Convert from impl coords */
+         gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
+         return tmp_region;
+
+       }
     }
   else
     return NULL;
@@ -3019,8 +4418,8 @@ _gdk_window_clear_update_area (GdkWindow *window)
 
   if (private->update_area)
     {
-      update_windows = g_slist_remove (update_windows, window);
-      
+      gdk_window_remove_update_window (window);
+
       gdk_region_destroy (private->update_area);
       private->update_area = NULL;
     }
@@ -3040,10 +4439,12 @@ void
 gdk_window_freeze_updates (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private->update_freeze_count++;
+  impl_window = gdk_window_get_impl_window (private);
+  impl_window->update_freeze_count++;
 }
 
 /**
@@ -3056,12 +4457,15 @@ void
 gdk_window_thaw_updates (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (private->update_freeze_count > 0);
 
-  if (--private->update_freeze_count == 0)
-    gdk_window_schedule_update (window);
+  impl_window = gdk_window_get_impl_window (private);
+  
+  if (--impl_window->update_freeze_count == 0)
+    gdk_window_schedule_update (GDK_WINDOW (impl_window));
 }
 
 /**
@@ -3389,6 +4793,101 @@ gdk_window_foreign_new (GdkNativeWindow anid)
   return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
 }
 
+/* Called when window becomes viewable. Clears and sends exposes
+   for all the already mapped windows in the hierarchy */
+static void
+synthesize_clears (GdkWindowObject *window)
+{
+  GList *l;
+  
+  if (!gdk_window_has_impl (window) && !window->input_only)
+    {
+      gdk_window_clear_area_e (GDK_WINDOW (window),
+                              0, 0,
+                              window->width, window->height);
+    }
+  
+  for (l = window->children; l != NULL; l = l->next)
+    {
+      GdkWindow *child = GDK_WINDOW (l->data);
+      
+      if (GDK_WINDOW_IS_MAPPED (child))
+       synthesize_clears (GDK_WINDOW_OBJECT (child));
+    }
+}
+
+static inline void
+gdk_window_raise_internal (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *parent = private->parent;
+
+  if (parent)
+    {
+      parent->children = g_list_remove (parent->children, window);
+      parent->children = g_list_prepend (parent->children, window);
+    }
+}
+
+static void
+gdk_window_show_internal (GdkWindow *window, gboolean raise)
+{
+  GdkWindowObject *private;
+  gboolean was_mapped;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
+  
+  if (raise)
+    {
+      /* Keep children in (reverse) stacking order */
+      gdk_window_raise_internal (window);
+    }
+
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, raise);
+  else
+    {
+      if (GDK_WINDOW_IS_MAPPED (window))
+       {
+         /* If we're raising, need to invalidate even if we're already shown */
+         if (raise && gdk_window_is_viewable (window) && !private->input_only)
+           gdk_window_invalidate_rect (window, NULL, TRUE);
+       }
+      else
+       {
+         /* Wasn't visible already */
+         private->state = 0;
+       }
+    }
+
+  if (!was_mapped)
+    {
+      if (private->event_mask & GDK_STRUCTURE_MASK)
+       _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+      
+      if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+       _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+    }
+  
+  if (!was_mapped || raise)
+    {
+      if (gdk_window_is_viewable (window))
+       _gdk_syntesize_crossing_events_for_geometry_change (window);
+      
+      recompute_visible_regions (private, TRUE, FALSE);
+    }
+  
+  if (!was_mapped && gdk_window_is_viewable (window))
+    synthesize_clears (private);
+  
+}
+  
 /**
  * gdk_window_show_unraised:
  * @window: a #GdkWindow
@@ -3404,28 +4903,7 @@ gdk_window_foreign_new (GdkNativeWindow anid)
 void
 gdk_window_show_unraised (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
-}
-
-static inline void
-gdk_window_raise_internal (GdkWindow *window)
-{
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *parent = private->parent;
-
-  if (parent)
-    {
-      parent->children = g_list_remove (parent->children, window);
-      parent->children = g_list_prepend (parent->children, window);
-    }
+  gdk_window_show_internal (window, FALSE);
 }
 
 /**
@@ -3455,6 +4933,8 @@ gdk_window_raise (GdkWindow *window)
   gdk_window_raise_internal (window);
 
   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
+
+  recompute_visible_regions (private, TRUE, FALSE);
 }
 
 static void
@@ -3470,6 +4950,30 @@ gdk_window_lower_internal (GdkWindow *window)
     }
 }
 
+static void
+gdk_window_invalidate_in_parent (GdkWindowObject *private)
+{
+  GdkRectangle r, child;
+
+  if (private->parent == NULL ||
+      GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    return;
+  
+  /* get the visible rectangle of the parent */
+  r.x = r.y = 0;
+  r.width = private->parent->width;
+  r.height = private->parent->height;
+
+  child.x = private->x;
+  child.y = private->y;
+  child.width = private->width;
+  child.height = private->height;
+  gdk_rectangle_intersect (&r, &child, &r);
+
+  gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
+}
+
+
 /**
  * gdk_window_lower:
  * @window: a #GdkWindow
@@ -3499,7 +5003,15 @@ gdk_window_lower (GdkWindow *window)
   /* Keep children in (reverse) stacking order */
   gdk_window_lower_internal (window);
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+  else
+    {
+      gdk_window_invalidate_in_parent (private);
+      _gdk_syntesize_crossing_events_for_geometry_change (window);
+    }
+
+  recompute_visible_regions (private, TRUE, FALSE);
 }
 
 /**
@@ -3519,18 +5031,7 @@ gdk_window_lower (GdkWindow *window)
 void
 gdk_window_show (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  /* Keep children in (reverse) stacking order */
-  gdk_window_raise_internal (window);
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, TRUE);
+  gdk_window_show_internal (window, TRUE);
 }
 
 /**
@@ -3546,6 +5047,7 @@ void
 gdk_window_hide (GdkWindow *window)
 {
   GdkWindowObject *private;
+  gboolean was_mapped;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -3553,7 +5055,50 @@ gdk_window_hide (GdkWindow *window)
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
+  was_mapped = GDK_WINDOW_IS_MAPPED (private);
+  
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
+  else if (was_mapped)
+    {
+      GdkDisplay *display;
+
+      /* May need to break grabs on children */
+      display = gdk_drawable_get_display (window);
+
+      if (display->pointer_grab.window != NULL)
+       {
+         if (is_parent_of (window, display->pointer_grab.window))
+           {
+             /* Call this ourselves, even though gdk_display_pointer_ungrab
+                does so too, since we want to pass implicit == TRUE so the
+                broken grab event is generated */
+             _gdk_display_unset_has_pointer_grab (display,
+                                                  TRUE,
+                                                  FALSE,
+                                                  GDK_CURRENT_TIME);
+             gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+           }
+       }
+
+      private->state = GDK_WINDOW_STATE_WITHDRAWN;
+      
+      /* Invalidate the rect */
+      gdk_window_invalidate_in_parent (private);
+    }
+
+  if (was_mapped)
+    {
+      if (private->event_mask & GDK_STRUCTURE_MASK)
+       _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+      
+      if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+       _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+      
+      _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+    }
+  
+  recompute_visible_regions (private, TRUE, FALSE);
 }
 
 /**
@@ -3568,6 +5113,7 @@ void
 gdk_window_withdraw (GdkWindow *window)
 {
   GdkWindowObject *private;
+  gboolean was_mapped;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -3575,7 +5121,25 @@ gdk_window_withdraw (GdkWindow *window)
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
+  was_mapped = GDK_WINDOW_IS_MAPPED (private);
+  
+  if (gdk_window_has_impl (private))
+    {
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
+      
+      if (was_mapped)
+       {
+         if (private->event_mask & GDK_STRUCTURE_MASK)
+           _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+         
+         if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+           _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+         
+         _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+       }
+      
+      recompute_visible_regions (private, TRUE, FALSE);
+    }
 }
 
 /**
@@ -3600,7 +5164,7 @@ gdk_window_set_events (GdkWindow       *window,
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, event_mask);
+  private->event_mask = event_mask;
 }
 
 /**
@@ -3622,9 +5186,189 @@ gdk_window_get_events (GdkWindow *window)
   if (private->destroyed)
     return 0;
 
-  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_events (window);
+  return private->event_mask;
+}
+
+static void
+move_native_children (GdkWindowObject *private)
+{
+  GList *l;
+  GdkWindowObject *child;
+  
+  for (l = private->children; l; l = l->next)
+    {
+      child = l->data;
+      
+      if (child->impl != private->impl)
+       GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
+      else
+       move_native_children  (child);
+    }
+}
+
+
+static void
+gdk_window_move_resize_internal (GdkWindow *window,
+                                gboolean   with_move,
+                                gint       x,
+                                gint       y,
+                                gint       width,
+                                gint       height)
+{
+  GdkWindowObject *private;
+  GdkRegion *old_region, *new_region, *copy_area;
+  GdkWindowObject *impl_window;
+  gboolean expose;
+  int old_x, old_y, old_abs_x, old_abs_y;
+  int dx, dy;
+  GdkRectangle copy_rect;
+  GdkGC *tmp_gc;
+  gboolean do_move_native_children;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  do_move_native_children = FALSE;
+  expose = FALSE;
+  old_region = NULL;
+
+  impl_window = gdk_window_get_impl_window (private);
+
+  old_x = private->x;
+  old_y = private->y;
+  
+  if (gdk_window_has_impl (private))
+    {
+      if (GDK_WINDOW_IS_MAPPED (window))
+       {
+         expose = TRUE;
+         old_region = gdk_region_copy (private->clip_region);
+         /* Adjust region to parent window coords */
+         gdk_region_offset (old_region, private->x, private->y);
+       }
+      
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
+    }
+  else
+    {
+      if (GDK_WINDOW_IS_MAPPED (window))
+       {
+         expose = TRUE;
+         old_region = gdk_region_copy (private->clip_region);
+         /* Adjust region to parent window coords */
+         gdk_region_offset (old_region, private->x, private->y);
+       }
+
+      if (with_move)
+       {
+         private->x = x;
+         private->y = y;
+       }
+      if (!(width < 0 && height < 0))
+       {
+         if (width < 1)
+           width = 1;
+         private->width = width;
+         if (height < 1)
+           height = 1;
+         private->height = height;
+       }
+
+      do_move_native_children = TRUE;
+    }
+
+  dx = private->x - old_x;
+  dy = private->y - old_y;
+
+  old_abs_x = private->abs_x;
+  old_abs_y = private->abs_y;
+  
+  recompute_visible_regions (private, TRUE, FALSE);
+
+  if (do_move_native_children &&
+      (old_abs_x != private->abs_x ||
+       old_abs_y != private->abs_y))
+      move_native_children (private);
+  
+  if (expose)
+    {
+      new_region = gdk_region_copy (private->clip_region);
+      /* Adjust region to parent window coords */
+      gdk_region_offset (new_region, private->x, private->y);
+
+      /* copy_area:
+       * Part of the data at the new location can be copied from the
+       * old location, this area is the intersection of the old region
+       * moved as the copy will move it and then intersected with
+       * the new region.
+       *
+       * new_region:
+       * Everything in the old and new regions that is not copied must be
+       * invalidated (including children) as this is newly exposed 
+       */
+      copy_area = gdk_region_copy (new_region);
+         
+      gdk_region_union (new_region, old_region);
+      
+      gdk_region_offset (old_region, dx, dy);
+      gdk_region_intersect (copy_area, old_region);
+      
+      gdk_region_subtract (new_region, copy_area);
+
+      /* Convert old region to impl coords */
+      gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
+
+      /* The old_region area is moved and we queue translations for all expose events
+        to it that will be sent before the copy operation */
+      /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
+      if (!gdk_window_is_offscreen (impl_window)) 
+       _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, old_region, dx, dy);
+      
+      /* convert from parent coords to real parent */
+      gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
+      gdk_region_get_clipbox (copy_area, &copy_rect);
+      tmp_gc = _gdk_drawable_get_scratch_gc (window, TRUE);
+      gdk_gc_set_clip_region (tmp_gc, copy_area);
+      gdk_draw_drawable (private->impl,
+                        tmp_gc,
+                        private->impl,
+                        copy_rect.x-dx, copy_rect.y-dy,
+                        copy_rect.x, copy_rect.y,
+                        copy_rect.width, copy_rect.height);
+      gdk_gc_set_clip_region (tmp_gc, NULL);
+
+      /* Move any old invalid regions in the copy source area by dx/dy */
+      if (impl_window->update_area)
+       {
+         /* Convert from target to source */
+         gdk_region_offset (copy_area, -dx, -dy);
+         gdk_region_intersect (copy_area, impl_window->update_area);
+         gdk_region_subtract (impl_window->update_area, copy_area);
+         gdk_region_offset (copy_area, dx, dy);
+         gdk_region_union (impl_window->update_area, copy_area);
+       }
+      
+      /* Invalidate affected part in the parent window
+       *  (no higher window should be affected)
+       * We also invalidate any children in that area, which could include
+       * this window if it still overlaps that area.
+       */
+      gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
+
+      
+      gdk_region_destroy (old_region);
+      gdk_region_destroy (new_region);
+      gdk_region_destroy (copy_area);
+    }
+
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
 }
 
+
+
 /**
  * gdk_window_move:
  * @window: a #GdkWindow
@@ -3645,16 +5389,8 @@ gdk_window_move (GdkWindow *window,
                 gint       x,
                 gint       y)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, -1, -1);
-}
+  gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
+}
 
 /**
  * gdk_window_resize:
@@ -3676,15 +5412,7 @@ gdk_window_resize (GdkWindow *window,
                   gint       width,
                   gint       height)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, FALSE, 0, 0, width, height);
+  gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
 }
 
 
@@ -3708,15 +5436,7 @@ gdk_window_move_resize (GdkWindow *window,
                        gint       width,
                        gint       height)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, width, height);
+  gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
 }
 
 
@@ -3744,6 +5464,11 @@ gdk_window_scroll (GdkWindow *window,
                   gint       dy)
 {
   GdkWindowObject *private = (GdkWindowObject *) window;
+  GdkWindowObject *impl_window;
+  GdkRegion *source_area, *copy_area, *noncopy_area;
+  GdkRectangle copy_rect;
+  GdkGC *tmp_gc;
+  GList *tmp_list;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -3753,7 +5478,88 @@ gdk_window_scroll (GdkWindow *window,
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->scroll (window, dx, dy);
+  /* First move all child windows, without causing invalidation */
+  
+  tmp_list = private->children;
+  while (tmp_list)
+    {
+      GdkWindow *child = GDK_WINDOW (tmp_list->data);
+      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
+      
+      if (child_obj->impl == private->impl)
+       {
+         /* Just update the positions, the bits will move with the copy */
+         child_obj->x += dx;
+         child_obj->y += dy;
+       }
+      else
+       {
+         /* Native window, need to move it */
+         GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, child_obj->x + dx, child_obj->y + dy, -1, -1);
+       }
+      
+      tmp_list = tmp_list->next;
+    }
+  
+  recompute_visible_regions (private, FALSE, TRUE);
+
+  /* Then copy the actual bits of the window w/ child windows */
+  
+  impl_window = gdk_window_get_impl_window (private);
+
+  /* Calculate the area that can be gotten by copying the old area */
+  copy_area = gdk_region_copy (private->clip_region);
+  gdk_region_offset (copy_area, dx, dy);
+  gdk_region_intersect (copy_area, private->clip_region);
+
+  /* And the rest need to be invalidated */
+  noncopy_area = gdk_region_copy (private->clip_region);
+  gdk_region_subtract (noncopy_area, copy_area);
+
+  /* Get window clip and convert to real window coords, this
+     area is moved and we queue translations for all expose events
+     to it that will be sent before the copy operation */
+  /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
+  if (!gdk_window_is_offscreen (impl_window))
+    {
+      source_area = gdk_region_copy (private->clip_region);
+      /* convert from window coords to real parent */
+      gdk_region_offset (source_area, private->abs_x, private->abs_y);
+      _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, source_area, dx, dy);
+      gdk_region_destroy (source_area);
+    }
+  
+  /* convert from window coords to real parent */
+  gdk_region_offset (copy_area, private->abs_x, private->abs_y);
+  gdk_region_get_clipbox (copy_area, &copy_rect);
+  tmp_gc = _gdk_drawable_get_scratch_gc (window, TRUE);
+  gdk_gc_set_clip_region (tmp_gc, copy_area);
+  gdk_draw_drawable (private->impl,
+                    tmp_gc,
+                    private->impl,
+                    copy_rect.x-dx, copy_rect.y-dy,
+                    copy_rect.x, copy_rect.y,
+                    copy_rect.width, copy_rect.height);
+  gdk_gc_set_clip_region (tmp_gc, NULL);
+
+  /* Move the current invalid region for the copy area */
+  if (private->update_area)
+    {
+      /* Convert from target to source */
+      gdk_region_offset (copy_area, -dx, -dy);
+      gdk_region_intersect (copy_area, impl_window->update_area);
+      gdk_region_subtract (impl_window->update_area, copy_area);
+      gdk_region_offset (copy_area, dx, dy);
+      gdk_region_union (impl_window->update_area, copy_area);
+    }
+  
+  /* Invalidate not copied regions */
+  gdk_window_invalidate_region (window, noncopy_area, TRUE);
+
+  gdk_region_destroy (noncopy_area);
+  gdk_region_destroy (copy_area);
+  
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
 }
 
 /**
@@ -3778,6 +5584,13 @@ gdk_window_move_region (GdkWindow       *window,
                        gint             dy)
 {
   GdkWindowObject *private = (GdkWindowObject *) window;
+  GdkWindowObject *impl_window;
+  GdkRegion *source_area;
+  GdkRegion *nocopy_area;
+  GdkRegion *copy_area;
+  GdkRegion *moving_invalid_region;
+  GdkRectangle copy_rect;
+  GdkGC *tmp_gc;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (region != NULL);
@@ -3788,7 +5601,57 @@ gdk_window_move_region (GdkWindow       *window,
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_region (window, region, dx, dy);
+  impl_window = gdk_window_get_impl_window (private);
+  
+  /* compute source regions */
+  source_area = gdk_region_copy (region);
+  gdk_region_intersect (source_area, private->clip_region_with_children);
+
+  /* compute destination regions */
+  copy_area = gdk_region_copy (source_area);
+  gdk_region_offset (copy_area, dx, dy);
+  gdk_region_intersect (copy_area, private->clip_region_with_children);
+
+  /* Move the current invalid region for the copy area */
+  if (impl_window->update_area)
+    {
+      moving_invalid_region = gdk_region_copy (copy_area);
+      gdk_region_offset (moving_invalid_region, private->abs_x - dx, private->abs_y - dy);
+      gdk_region_intersect (moving_invalid_region, impl_window->update_area);
+      gdk_region_subtract (impl_window->update_area, moving_invalid_region);
+      gdk_region_offset (moving_invalid_region, dx, dy);
+      gdk_region_union (impl_window->update_area, moving_invalid_region);
+      gdk_region_destroy (moving_invalid_region);
+    }
+  
+  /* invalidate parts of the region not covered by the copy */
+  nocopy_area = gdk_region_copy (region);
+  gdk_region_offset (nocopy_area, dx, dy);
+  gdk_region_subtract (nocopy_area, copy_area);
+  gdk_window_invalidate_region (window, nocopy_area, FALSE);
+  gdk_region_destroy (nocopy_area);
+
+  /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
+  if (!gdk_window_is_offscreen (impl_window))
+    {
+      gdk_region_offset (source_area, private->abs_x, private->abs_y);
+      _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, source_area, dx, dy);
+    }
+
+  gdk_region_offset (copy_area, private->abs_x, private->abs_y);
+  gdk_region_get_clipbox (copy_area, &copy_rect);
+  tmp_gc = _gdk_drawable_get_scratch_gc (window, TRUE);
+  gdk_gc_set_clip_region (tmp_gc, copy_area);
+  gdk_draw_drawable (private->impl,
+                    tmp_gc,
+                    private->impl,
+                    copy_rect.x-dx, copy_rect.y-dy,
+                    copy_rect.x, copy_rect.y,
+                    copy_rect.width, copy_rect.height);
+  gdk_gc_set_clip_region (tmp_gc, NULL);
+
+  gdk_region_destroy (source_area);
+  gdk_region_destroy (copy_area);
 }
 
 /**
@@ -3811,12 +5674,24 @@ gdk_window_set_background (GdkWindow      *window,
                           const GdkColor *color)
 {
   GdkWindowObject *private;
+  GdkColormap *colormap = gdk_drawable_get_colormap (window);
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   private = (GdkWindowObject *) window;
+  
+  private->bg_color = *color;
+  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
+
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+  
+  private->bg_pixmap = NULL;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, color);
+  if (!GDK_WINDOW_DESTROYED (window) && gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
 }
 
 /**
@@ -3858,7 +5733,26 @@ gdk_window_set_back_pixmap (GdkWindow *window,
 
   private = (GdkWindowObject *) window;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, pixmap, parent_relative);
+  if (pixmap && !gdk_drawable_get_colormap (pixmap))
+    {
+      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+      return;
+    }
+  
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+
+  if (parent_relative)
+    private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
+  else if (pixmap)
+    private->bg_pixmap = g_object_ref (pixmap);
+  else
+    private->bg_pixmap = GDK_NO_BG;
+  
+  if (!GDK_WINDOW_DESTROYED (window) && gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
 }
 
 /**
@@ -3882,7 +5776,21 @@ gdk_window_set_cursor (GdkWindow *window,
 
   private = (GdkWindowObject *) window;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
+  if (private->cursor)
+    {
+      gdk_cursor_unref (private->cursor);
+      private->cursor = NULL;
+    }
+
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      if (cursor)
+       private->cursor = gdk_cursor_ref (cursor);
+
+      /* TODO: Track this via pointer_window 
+        GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
+      */
+    }
 }
 
 /**
@@ -3941,9 +5849,23 @@ gdk_window_get_geometry (GdkWindow *window,
 
   if (!GDK_WINDOW_DESTROYED (window))
     {
-      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
-                                                              width, height,
-                                                               depth);
+      if (gdk_window_has_impl (private))
+       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
+                                                                width, height,
+                                                                depth);
+      else
+       {
+         if (x)
+           *x = private->x;
+         if (y)
+           *y = private->y;
+         if (width)
+           *width = private->width;
+         if (height)
+           *height = private->height;
+         if (depth)
+           *depth = private->depth;
+       }
     }
 }
 
@@ -3970,8 +5892,15 @@ gdk_window_get_origin (GdkWindow *window,
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
   private = (GdkWindowObject *) window;
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
 
-  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
+  if (x)
+    *x += private->abs_x;
+  if (y)
+    *y += private->abs_y;
+  
+  return TRUE;
 }
 
 /**
@@ -4119,7 +6048,10 @@ gdk_window_set_static_gravities (GdkWindow *window,
 
   private = (GdkWindowObject *) window;
 
-  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+  if (gdk_window_has_impl (private))
+    return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+  
+  return FALSE;
 }
 
 /**
@@ -4285,7 +6217,7 @@ gdk_window_redirect_to_drawable (GdkWindow   *window,
                                  gint         height)
 {
   GdkWindowObject *private;
-  
+
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
@@ -4322,20 +6254,22 @@ static void
 window_get_size_rectangle (GdkWindow    *window,
                            GdkRectangle *rect)
 {
+  GdkWindowObject *private = (GdkWindowObject *) window;
+  
   rect->x = rect->y = 0;
-  gdk_drawable_get_size (GDK_DRAWABLE (window), &rect->width, &rect->height);
+  rect->width = private->width;
+  rect->height = private->height;
 }
 
 /* Calculates the real clipping region for a window, in window coordinates,
  * taking into account other windows, gc clip region and gc clip mask.
  */
-static GdkRegion *
+GdkRegion *
 _gdk_window_calculate_full_clip_region (GdkWindow *window,
                                        GdkWindow *base_window,
-                                       GdkGC *gc,
-                                       gboolean do_children,
-                                       gint *base_x_offset,
-                                       gint *base_y_offset)
+                                       gboolean   do_children,
+                                       gint      *base_x_offset,
+                                       gint      *base_y_offset)
 {
   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
   GdkRectangle visible_rect;
@@ -4353,13 +6287,6 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
 
   window_get_size_rectangle (window, &visible_rect);
 
-  /* windows that a redirection has ben setup for need to be considered
-   * fully visible, in order to avoid missing redirected paint ops
-   * anywhere in the window area.
-   */
-  if (private->redirect && private->redirect->redirected == private)
-    return gdk_region_rectangle (&visible_rect);
-
   /* real_clip_region is in window coordinates */
   real_clip_region = gdk_region_rectangle (&visible_rect);
 
@@ -4372,27 +6299,38 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
     parentwin = lastwin->parent;
   
   /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
-  for (; parentwin != NULL && (parentwin == private || lastwin != (GdkWindowObject *)base_window);
+  for (; parentwin != NULL &&
+         (parentwin == private || lastwin != (GdkWindowObject*) base_window);
        lastwin = parentwin, parentwin = lastwin->parent)
     {
       GList *cur;
       GdkRectangle real_clip_rect;
-      
+      gboolean is_offscreen;
+
       if (parentwin != private)
        {
          x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
          y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
        }
-      
+
+      is_offscreen = gdk_window_is_offscreen (parentwin);
+
       /* children is ordered in reverse stack order */
-      for (cur = GDK_WINDOW_OBJECT (parentwin)->children; cur && cur->data != lastwin; cur = cur->next)
+      for (cur = parentwin->children;
+           cur && cur->data != lastwin;
+           cur = cur->next)
        {
          GdkWindow *child = cur->data;
          GdkWindowObject *child_private = (GdkWindowObject *)child;
-         
+
          if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
            continue;
 
+          /* Ignore offscreen children, as they don't draw in their parent and
+          * don't take part in the clipping */
+         if (gdk_window_is_offscreen (child_private))
+           continue;
+
           window_get_size_rectangle (child, &visible_rect);
 
          /* Convert rect to "window" coords */
@@ -4423,24 +6361,6 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
       gdk_region_destroy (tmpreg);
     }
 
-  if (gc)
-    {
-      GdkRegion *clip_region = _gdk_gc_get_clip_region (gc);
-      
-      if (clip_region)
-       {
-         /* clip_region is relative to gc clip origin which is relative to the window */
-         /* offset it to window relative: */
-         tmpreg = gdk_region_copy (clip_region);
-         gdk_region_offset (real_clip_region,
-                            gc->clip_x_origin,
-                            gc->clip_y_origin);
-         /* Intersect it with window hierarchy cliprect: */
-         gdk_region_intersect (real_clip_region, tmpreg);
-         gdk_region_destroy (tmpreg);
-       }
-    }
-
   if (base_x_offset)
     *base_x_offset = x_offset;
   if (base_y_offset)
@@ -4449,9 +6369,9 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
   return real_clip_region;
 }
 
-static void
-gdk_window_add_damage (GdkWindow *toplevel,
-                      GdkRegion *damaged_region)
+void
+_gdk_window_add_damage (GdkWindow *toplevel,
+                       GdkRegion *damaged_region)
 {
   GdkDisplay *display;
   GdkEvent event = { 0, };
@@ -4465,80 +6385,903 @@ gdk_window_add_damage (GdkWindow *toplevel,
 }
 
 static void
-setup_redirect_clip (GdkWindow         *window,
-                    GdkGC             *gc,
-                    GdkWindowClipData *data)
+gdk_window_redirect_free (GdkWindowRedirect *redirect)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkRegion *visible_region;
-  GdkRectangle dest_rect;
-  GdkRegion *tmpreg;
-  GdkWindow *toplevel;
+  g_object_unref (redirect->pixmap);
+  g_free (redirect);
+}
 
-  data->old_region = _gdk_gc_get_clip_region (gc);
-  if (data->old_region) 
-    data->old_region = gdk_region_copy (data->old_region);
+static void
+convert_coords_to_child (GdkWindowObject *child,
+                        double x, double y,
+                        double *child_x, double *child_y)
+{
+  *child_x = x - child->x;
+  *child_y = y - child->y;
 
-  data->old_clip_x_origin = gc->clip_x_origin;
-  data->old_clip_y_origin = gc->clip_y_origin;
+  if (child->offscreen_hooks)
+    child->offscreen_hooks->from_parent ((GdkWindow *)child, x, y, child_x, child_y);
+}
 
-  toplevel = GDK_WINDOW (private->redirect->redirected);
+static gboolean
+point_in_window (GdkWindowObject *window,
+                double x, double y)
+{
+  int w, h;
   
-  /* Get the clip region for gc clip rect + window hierarchy in
-     window relative coords */
-  visible_region =
-    _gdk_window_calculate_full_clip_region (window, toplevel,
-                                           gc, TRUE,
-                                           &data->x_offset, 
-                                           &data->y_offset);
+  gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+  
+  return
+    x >= 0 &&  x < w &&
+    y >= 0 && y < h;
+}
 
-  /* Compensate for the source pos/size */
-  data->x_offset -= private->redirect->src_x;
-  data->y_offset -= private->redirect->src_y;
-  dest_rect.x = -data->x_offset;
-  dest_rect.y = -data->y_offset;
-  dest_rect.width = private->redirect->width;
-  dest_rect.height = private->redirect->height;
-  tmpreg = gdk_region_rectangle (&dest_rect);
-  gdk_region_intersect (visible_region, tmpreg);
-  gdk_region_destroy (tmpreg);
+static void
+convert_toplevel_coords_to_window (GdkWindow *window,
+                                  gdouble    toplevel_x,
+                                  gdouble    toplevel_y,
+                                  gdouble   *window_x,
+                                  gdouble   *window_y)
+{
+  GdkWindowObject *private;
+  gdouble x, y;
+  GList *children, *l;
 
-  /* Compensate for the dest pos */
-  data->x_offset += private->redirect->dest_x;
-  data->y_offset += private->redirect->dest_y;
+  private = GDK_WINDOW_OBJECT (window);
+  
+  x = toplevel_x;
+  y = toplevel_y;
 
-  gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
+  children = NULL;
+  while (private->parent != NULL &&
+        (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+    {
+      children = g_list_prepend (children, private);
+      private = private->parent;
+    }
 
-  /* offset clip and tiles from window coords to pixmaps coords */
-  gdk_gc_offset (gc, -data->x_offset, -data->y_offset);
+  for (l = children; l != NULL; l = l->next)
+    convert_coords_to_child (l->data, x, y, &x, &y);
+  
+  g_list_free (children);
+  
+  *window_x = x;
+  *window_y = y;
+}
+
+GdkWindow *
+_gdk_window_find_descendant_at (GdkWindow *toplevel,
+                               double x, double y,
+                               double *found_x,
+                               double *found_y)
+{
+  GdkWindowObject *private, *sub;
+  double child_x, child_y;
+  GList *l;
 
-  /* Offset region to abs coords and add to damage */
-  gdk_region_offset (visible_region, data->x_offset, data->y_offset);
-  gdk_window_add_damage (toplevel, visible_region);
+  private = (GdkWindowObject *)toplevel;
   
-  gdk_region_destroy (visible_region);
+  if (point_in_window (private, x, y))
+    {
+      do 
+       {
+         /* Children is ordered in reverse stack order, i.e. first is topmost */
+         for (l = private->children; l != NULL; l = l->next)
+           {
+             sub = l->data;
+
+              if (!GDK_WINDOW_IS_MAPPED (sub))
+                continue;
+             
+             convert_coords_to_child (sub,
+                                      x, y,
+                                      &child_x, &child_y);
+             if (point_in_window (sub, child_x, child_y))
+               {
+                 x = child_x;
+                 y = child_y;
+                 private = sub;
+                 break;
+               }
+           }
+       }
+      while (l != NULL);
+    }
+  else
+    {
+      /* Not in window at all */
+      private = NULL;
+    }
+
+  if (found_x)
+    *found_x = x;
+  if (found_y)
+    *found_y = y;
+  
+  return (GdkWindow *)private;
 }
 
-static void
-reset_redirect_clip (GdkWindow         *offscreen,
-                     GdkGC             *gc,
-                     GdkWindowClipData *data)
+static const guint type_masks[] = {
+  GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE                 = 0  */
+  GDK_STRUCTURE_MASK, /* GDK_DESTROY                   = 1  */
+  GDK_EXPOSURE_MASK, /* GDK_EXPOSE                     = 2  */
+  GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY        = 3  */
+  GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS           = 4  */
+  GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS          = 5  */
+  GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS          = 6  */
+  GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE       = 7  */
+  GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS                 = 8  */
+  GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE             = 9  */
+  GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY           = 10 */
+  GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY           = 11 */
+  GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE           = 12 */
+  GDK_STRUCTURE_MASK, /* GDK_CONFIGURE                 = 13 */
+  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP               = 14 */
+  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP             = 15 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY     = 16 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR     = 17 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST   = 18 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY    = 19 */
+  GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN           = 20 */
+  GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT         = 21 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER               = 22 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE               = 23 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION              = 24 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS              = 25 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DROP_START               = 26 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED            = 27 */
+  GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT            = 28 */
+  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
+  GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE                  = 30 */
+  GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
+  0, /* GDK_WINDOW_STATE = 32 */
+  0, /* GDK_SETTING = 33 */
+  0, /* GDK_OWNER_CHANGE = 34 */
+  0, /* GDK_GRAB_BROKEN = 35 */
+  0, /* GDK_DAMAGE = 36 */
+};
+G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
+
+/* send motion events if the right buttons are down */
+static guint
+update_evmask_for_button_motion (guint           evmask,
+                                 GdkModifierType mask)
+{
+  if (evmask & GDK_BUTTON_MOTION_MASK &&
+      mask & (GDK_BUTTON1_MASK |
+             GDK_BUTTON2_MASK |
+             GDK_BUTTON3_MASK |
+             GDK_BUTTON4_MASK |
+             GDK_BUTTON5_MASK))
+    evmask |= GDK_POINTER_MOTION_MASK;
+
+  if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
+      (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
+      (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
+    evmask |= GDK_POINTER_MOTION_MASK;
+
+  return evmask;
+}
+
+static GdkWindow *
+get_target_window_for_pointer_event (GdkDisplay                 *display,
+                                    GdkWindow                  *window,
+                                     GdkEventType                type,
+                                     GdkModifierType             mask)
 {
-  /* offset back */
-  gdk_gc_offset (gc, data->x_offset, data->y_offset);
+  guint evmask;
+  gboolean crossing_event;
+  GdkWindow *w, *grab_window;
+
+  /* crossing events don't propagate up like other types of events */
+  crossing_event = (type == GDK_ENTER_NOTIFY || type == GDK_LEAVE_NOTIFY);
+
+  if ((display->pointer_grab.window != NULL && !display->pointer_grab.owner_events) ||
+      (type == GDK_BUTTON_RELEASE && display->pointer_grab.grab_one_pointer_release_event))
+    {
+      evmask = display->pointer_grab.event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
+
+      if (type == GDK_BUTTON_RELEASE &&
+         display->pointer_grab.grab_one_pointer_release_event)
+       {
+         grab_window = display->pointer_grab.grab_one_pointer_release_event;
+         display->pointer_grab.grab_one_pointer_release_event = NULL;
+       }
+      else
+       grab_window = display->pointer_grab.window;
+
+      if ((evmask & type_masks[type]) &&
+          (!crossing_event || window == grab_window))
+       return grab_window;
+      else
+       return NULL;
+    }
+
+  w = window;
+  while (w != NULL)
+    {
+      evmask = GDK_WINDOW_OBJECT(window)->event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
+
+      if (evmask & type_masks[type])
+       return w;
 
-  /* reset old clip */
-  gdk_gc_set_clip_region (gc, data->old_region);
-  if (data->old_region)
-    gdk_region_destroy (data->old_region);
-  gdk_gc_set_clip_origin (gc, data->old_clip_x_origin, data->old_clip_y_origin);
+      if (crossing_event)
+       break;
+
+      w = gdk_window_get_parent (w);
+    }
+
+  if (display->pointer_grab.window != NULL &&
+      display->pointer_grab.owner_events)
+    {
+      evmask = display->pointer_grab.event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
+
+      if ((evmask & type_masks[type]) &&
+         (!crossing_event || window == display->pointer_grab.window))
+       return display->pointer_grab.window;
+      else
+       return NULL;
+    }
+
+  return NULL;
 }
 
-static void
-gdk_window_redirect_free (GdkWindowRedirect *redirect)
+
+static gboolean
+is_button_type (GdkEventType type)
 {
-  g_object_unref (redirect->pixmap);
-  g_free (redirect);
+  return type == GDK_BUTTON_PRESS ||
+         type == GDK_2BUTTON_PRESS ||
+         type == GDK_3BUTTON_PRESS ||
+         type == GDK_BUTTON_RELEASE ||
+         type == GDK_SCROLL;
+}
+
+static gboolean
+is_motion_type (GdkEventType type)
+{
+  return type == GDK_MOTION_NOTIFY ||
+         type == GDK_ENTER_NOTIFY ||
+         type == GDK_LEAVE_NOTIFY;
+}
+
+static GdkWindow *
+find_common_ancestor (GdkWindow *win1,
+                     GdkWindow *win2)
+{
+  GdkWindowObject *tmp;
+  GList *path1 = NULL, *path2 = NULL;
+  GList *list1, *list2;
+
+  tmp = GDK_WINDOW_OBJECT (win1);
+  while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
+    {
+      path1 = g_list_prepend (path1, tmp);
+      tmp = tmp->parent;
+    }
+
+  tmp = GDK_WINDOW_OBJECT (win2);
+  while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
+    {
+      path2 = g_list_prepend (path2, tmp);
+      tmp = tmp->parent;
+    }
+
+  list1 = path1;
+  list2 = path2;
+  tmp = NULL;
+  while (list1 && list2 && (list1->data == list2->data))
+    {
+      tmp = (GdkWindowObject *)list1->data;
+      list1 = g_list_next (list1);
+      list2 = g_list_next (list2);
+    }
+  g_list_free (path1);
+  g_list_free (path2);
+
+  return GDK_WINDOW (tmp);
+}
+
+GdkEvent *
+_gdk_make_event (GdkWindow    *window,
+                GdkEventType  type,
+                GdkEvent     *event_in_queue,
+                gboolean      before_event)
+{
+  GdkEvent *event = gdk_event_new (type);
+  guint32 the_time;
+  GdkModifierType the_state;
+
+  the_time = gdk_event_get_time (event_in_queue);
+  gdk_event_get_state (event_in_queue, &the_state);
+
+  event->any.window = g_object_ref (window);
+  event->any.send_event = FALSE;
+
+  switch (type)
+    {
+    case GDK_MOTION_NOTIFY:
+      event->motion.time = the_time;
+      event->motion.axes = NULL;
+      event->motion.state = the_state;
+      break;
+
+    case GDK_BUTTON_PRESS:
+    case GDK_2BUTTON_PRESS:
+    case GDK_3BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+      event->button.time = the_time;
+      event->button.axes = NULL;
+      event->button.state = the_state;
+      break;
+
+    case GDK_SCROLL:
+      event->scroll.time = the_time;
+      event->scroll.state = the_state;
+      break;
+
+    case GDK_KEY_PRESS:
+    case GDK_KEY_RELEASE:
+      event->key.time = the_time;
+      event->key.state = the_state;
+      break;
+
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+      event->crossing.time = the_time;
+      event->crossing.state = the_state;
+      break;
+
+    case GDK_PROPERTY_NOTIFY:
+      event->property.time = the_time;
+      event->property.state = the_state;
+      break;
+
+    case GDK_SELECTION_CLEAR:
+    case GDK_SELECTION_REQUEST:
+    case GDK_SELECTION_NOTIFY:
+      event->selection.time = the_time;
+      break;
+
+    case GDK_PROXIMITY_IN:
+    case GDK_PROXIMITY_OUT:
+      event->proximity.time = the_time;
+      break;
+
+    case GDK_DRAG_ENTER:
+    case GDK_DRAG_LEAVE:
+    case GDK_DRAG_MOTION:
+    case GDK_DRAG_STATUS:
+    case GDK_DROP_START:
+    case GDK_DROP_FINISHED:
+      event->dnd.time = the_time;
+      break;
+
+    case GDK_FOCUS_CHANGE:
+    case GDK_CONFIGURE:
+    case GDK_MAP:
+    case GDK_UNMAP:
+    case GDK_CLIENT_EVENT:
+    case GDK_VISIBILITY_NOTIFY:
+    case GDK_NO_EXPOSE:
+    case GDK_DELETE:
+    case GDK_DESTROY:
+    case GDK_EXPOSE:
+    default:
+      break;
+    }
+
+  if (event_in_queue)
+    {
+    if (before_event)
+      _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
+    else
+      _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
+    }
+  else
+    _gdk_event_queue_append (gdk_drawable_get_display (window), event);
+
+  return event;
+}
+
+/* The coordinates are in the toplevel window that src/dest are in.
+ * src and dest are always (if != NULL) in the same toplevel, as
+ * we get a leave-notify and set the window_under_pointer to null
+ * before crossing to another toplevel.
+ */
+void
+_gdk_syntesize_crossing_events (GdkDisplay                 *display,
+                               GdkWindow                  *src,
+                               GdkWindow                  *dest,
+                               GdkCrossingMode             mode,
+                               gint                        toplevel_x,
+                               gint                        toplevel_y,
+                               GdkModifierType             mask,
+                               guint32                     time_,
+                               gboolean                    do_first,
+                               gboolean                    do_last)
+{
+  GdkWindow *c;
+  GdkWindow *win, *last, *next;
+  GdkEvent *event;
+  GList *path, *list;
+  gboolean non_linear;
+  GdkWindow *a;
+  GdkWindow *b;
+  GdkWindow *event_win;
+
+  /* TODO: Don't send events to toplevel, as we get those from the windowing system */
+  
+  a = src;
+  b = dest;
+  if (a == b)
+    return; /* No crossings generated between src and dest */
+  
+  c = find_common_ancestor (a, b);
+  non_linear = (c != a) && (c != b);
+
+  if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
+    {
+      /* Traverse up from a to (excluding) c sending leave events */
+
+      event_win = get_target_window_for_pointer_event (display, a, GDK_LEAVE_NOTIFY, mask);
+      if (do_first && event_win)
+       {
+         event = _gdk_make_event (event_win, GDK_LEAVE_NOTIFY, NULL, FALSE);
+         event->crossing.time = time_;
+         event->crossing.subwindow = NULL;
+         convert_toplevel_coords_to_window (event_win,
+                                            toplevel_x, toplevel_y,
+                                            &event->crossing.x, &event->crossing.y);
+         event->crossing.x_root = toplevel_x;
+         event->crossing.y_root = toplevel_y;
+         event->crossing.mode = mode;
+         if (non_linear)
+           event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+         else if (c == a)
+           event->crossing.detail = GDK_NOTIFY_INFERIOR;
+         else
+           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+         event->crossing.focus = FALSE;
+         event->crossing.state = mask;
+       }
+      
+      if (c != a)
+       {
+         last = a;
+         win = GDK_WINDOW (GDK_WINDOW_OBJECT (a)->parent);
+         while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
+           {
+             event_win = get_target_window_for_pointer_event (display, win, GDK_LEAVE_NOTIFY, mask);
+             if (event_win)
+               {
+                 event = _gdk_make_event (event_win, GDK_LEAVE_NOTIFY, NULL, FALSE);
+                 event->crossing.time = time_;
+                 event->crossing.subwindow = g_object_ref (last);
+                 convert_toplevel_coords_to_window (event_win,
+                                                    toplevel_x, toplevel_y,
+                                                    &event->crossing.x, &event->crossing.y);
+                 event->crossing.x_root = toplevel_x;
+                 event->crossing.y_root = toplevel_y;
+                 event->crossing.mode = mode;
+                 if (non_linear)
+                   event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+                 else
+                   event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+                 event->crossing.focus = FALSE;
+                 event->crossing.state = mask;
+               }
+             last = win;
+             win = GDK_WINDOW (GDK_WINDOW_OBJECT (win)->parent);
+           }
+       }
+    }
+
+  if (b) /* Might not be a dest, e.g. if we're moving out of the window */
+    {
+      /* Traverse down from c to b */
+      if (c != b)
+       {
+         path = NULL;
+         win = GDK_WINDOW (GDK_WINDOW_OBJECT (b)->parent);
+         while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
+           {
+             path = g_list_prepend (path, win);
+             win = GDK_WINDOW( GDK_WINDOW_OBJECT (win)->parent);
+           }
+         
+         list = path;
+         while (list)
+           {
+             win = (GdkWindow *)list->data;
+             list = g_list_next (list);
+             if (list)
+               next = (GdkWindow *)list->data;
+             else
+               next = b;
+             
+             event_win = get_target_window_for_pointer_event (display, win, GDK_ENTER_NOTIFY, mask);
+             if (event_win)
+               {
+                 event = _gdk_make_event (event_win, GDK_ENTER_NOTIFY, NULL, FALSE);
+                 event->crossing.time = time_;
+                 event->crossing.subwindow = g_object_ref (next);
+                 convert_toplevel_coords_to_window (event_win,
+                                                    toplevel_x, toplevel_y,
+                                                    &event->crossing.x, &event->crossing.y);
+                 event->crossing.x_root = toplevel_x;
+                 event->crossing.y_root = toplevel_y;
+                 event->crossing.mode = mode;
+                 if (non_linear)
+                   event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+                 else
+                   event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+                 event->crossing.focus = FALSE;
+                 event->crossing.state = mask;
+               }
+           }
+         g_list_free (path);
+       }
+      
+      event_win = get_target_window_for_pointer_event (display, b, GDK_ENTER_NOTIFY, mask);
+      if (do_last && event_win)
+       {
+         event = _gdk_make_event (event_win, GDK_ENTER_NOTIFY, NULL, FALSE);
+         event->crossing.time = time_;
+         event->crossing.subwindow = NULL;
+         convert_toplevel_coords_to_window (event_win,
+                                            toplevel_x, toplevel_y,
+                                            &event->crossing.x, &event->crossing.y);
+         event->crossing.x_root = toplevel_x;
+         event->crossing.y_root = toplevel_y;
+         event->crossing.mode = mode;
+         if (non_linear)
+           event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+         else if (c == a)
+           event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+         else
+           event->crossing.detail = GDK_NOTIFY_INFERIOR;
+         event->crossing.focus = FALSE;
+         event->crossing.state = mask;
+       }
+    }
+
+}
+
+static GdkWindow *
+get_toplevel (GdkWindow *w)
+{
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
+  
+  while (private->parent != NULL &&
+        (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+    private = private->parent;
+
+  return GDK_WINDOW (private);
+}
+
+void
+_gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
+{
+  GdkDisplay *display;
+  GdkWindow *changed_toplevel;
+  GdkWindow *pointer_toplevel;
+  GdkWindow *new_window_under_pointer;
+
+  changed_toplevel = get_toplevel (changed_window);
+  
+  display = gdk_drawable_get_display (changed_window);
+  if (display->pointer_info.window_under_pointer)
+    {
+      pointer_toplevel = get_toplevel (display->pointer_info.window_under_pointer);
+
+      if (pointer_toplevel == changed_toplevel)
+       {
+         new_window_under_pointer =
+           _gdk_window_find_descendant_at (pointer_toplevel,
+                                           display->pointer_info.toplevel_x,
+                                           display->pointer_info.toplevel_y,
+                                           NULL, NULL);
+         if (new_window_under_pointer !=
+             display->pointer_info.window_under_pointer)
+           {
+             _gdk_syntesize_crossing_events (display,
+                                             display->pointer_info.window_under_pointer,
+                                             new_window_under_pointer,
+                                             GDK_CROSSING_NORMAL,
+                                             display->pointer_info.toplevel_x,
+                                             display->pointer_info.toplevel_y,
+                                             display->pointer_info.state,
+                                             GDK_CURRENT_TIME,
+                                             TRUE, TRUE);
+             
+             if (display->pointer_info.window_under_pointer)
+               g_object_unref (display->pointer_info.window_under_pointer);
+             display->pointer_info.window_under_pointer = NULL;
+             if (new_window_under_pointer)
+               display->pointer_info.window_under_pointer = g_object_ref (new_window_under_pointer);
+           }
+       }
+    }
+}
+
+static gboolean
+proxy_pointer_event (GdkDisplay                 *display,
+                    GdkWindow                  *pointer_window,
+                    gdouble                     toplevel_x,
+                     gdouble                     toplevel_y,
+                    GdkEvent                   *source_event)
+{
+  GdkWindow *event_window;
+  GdkWindow *event_win, *cursor_window;
+  gboolean crossing_event;
+  gboolean sent_motion;
+  GdkEvent *event;
+  guint state;
+  guint32 time_;
+
+  event_window = source_event->any.window;
+  
+  gdk_event_get_state (source_event, &state);
+  time_ = gdk_event_get_time (source_event);
+
+  crossing_event =
+    source_event->type == GDK_ENTER_NOTIFY ||
+    source_event->type == GDK_LEAVE_NOTIFY;
+
+  if (crossing_event)
+    {
+      GdkEventCrossing *crossing = &source_event->crossing;
+
+      if (crossing->mode == GDK_CROSSING_GRAB)
+       {
+         if (crossing->type == GDK_LEAVE_NOTIFY &&
+             display->pointer_info.window_under_pointer != NULL)
+           {
+             _gdk_syntesize_crossing_events (display,
+                                             display->pointer_info.window_under_pointer,
+                                             event_window,
+                                             GDK_CROSSING_GRAB,
+                                             toplevel_x, toplevel_y, state, time_,
+                                             TRUE, FALSE);
+           }
+
+         if (crossing->type == GDK_ENTER_NOTIFY &&
+             display->pointer_grab.window != NULL)
+           {
+             _gdk_syntesize_crossing_events (display,
+                                             event_window,
+                                             display->pointer_grab.window,
+                                             GDK_CROSSING_GRAB,
+                                             toplevel_x, toplevel_y, state, time_,
+                                             FALSE, TRUE);
+           }
+       }
+
+      if (crossing->mode == GDK_CROSSING_UNGRAB)
+       {
+         if (crossing->type == GDK_LEAVE_NOTIFY &&
+             display->pointer_grab.window != NULL)
+           {
+             _gdk_syntesize_crossing_events (display,
+                                             display->pointer_grab.window,
+                                             event_window,
+                                             GDK_CROSSING_UNGRAB,
+                                             toplevel_x, toplevel_y, state, time_,
+                                             TRUE, FALSE);
+           }
+
+         if (crossing->type == GDK_ENTER_NOTIFY &&
+             display->pointer_info.window_under_pointer != NULL)
+           {
+             _gdk_syntesize_crossing_events (display,
+                                             event_window,
+                                             display->pointer_info.window_under_pointer,
+                                             GDK_CROSSING_UNGRAB,
+                                             toplevel_x, toplevel_y, state, time_,
+                                             FALSE, TRUE);
+           }
+       }
+    }
+
+  cursor_window = pointer_window;
+  if (display->pointer_grab.window &&
+      (pointer_window == NULL ||
+       !is_parent_of (display->pointer_grab.window, pointer_window)))
+    cursor_window = display->pointer_grab.window;
+
+  /* TODO: set cursor from cursor_window, or grab cursor */
+
+  sent_motion = FALSE;
+  if (!crossing_event &&
+      (display->pointer_info.window_under_pointer == pointer_window ||
+       (display->pointer_grab.window != NULL &&
+       !display->pointer_grab.owner_events)))
+    {
+      /* send motion events */
+      event_win = get_target_window_for_pointer_event (display, pointer_window, GDK_MOTION_NOTIFY, state);
+      if (event_win)
+       {
+         sent_motion = TRUE;
+         event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
+         event->motion.time = time_;
+         convert_toplevel_coords_to_window (event_win,
+                                            toplevel_x, toplevel_y,
+                                            &event->motion.x, &event->motion.y);
+         event->motion.x_root = toplevel_x; /* TODO: right? */
+         event->motion.y_root = toplevel_y;
+         event->motion.state = state;
+         event->motion.is_hint = FALSE;
+         event->motion.device = NULL;
+         if (source_event && source_event->type == GDK_MOTION_NOTIFY)
+           event->motion.device = source_event->motion.device;
+       }
+    }
+
+  _gdk_syntesize_crossing_events (display,
+                                 display->pointer_info.window_under_pointer,
+                                 pointer_window,
+                                 GDK_CROSSING_NORMAL,
+                                 toplevel_x, toplevel_y,
+                                 state, time_,
+                                 TRUE, TRUE);
+
+  /* unlink move event from parent if we sent a motion event */
+  return source_event->type == GDK_MOTION_NOTIFY && sent_motion;
+}
+
+static gboolean
+proxy_button_event (GdkWindow                  *pointer_window,
+                   gdouble                     toplevel_x,
+                    gdouble                     toplevel_y,
+                   GdkEvent                   *source_event)
+{
+  GdkWindow *event_win;
+  GdkEvent *event;
+  guint state;
+  guint32 time_;
+  GdkEventType type;
+  GdkDisplay *display;
+
+  type = source_event->any.type;
+  gdk_event_get_state (source_event, &state);
+  time_ = gdk_event_get_time (source_event);
+  display = gdk_drawable_get_display (source_event->any.window);
+  
+  if ((type == GDK_BUTTON_PRESS || type == GDK_SCROLL) &&
+      pointer_window != NULL &&
+      display->pointer_grab.window == source_event->any.window &&
+      display->pointer_grab.implicit &&
+      !display->pointer_grab.converted_implicit)
+    {
+      if (pointer_window != source_event->any.window)
+       _gdk_display_set_has_pointer_grab (display,
+                                          pointer_window,
+                                          display->pointer_grab.native_window,
+                                          display->pointer_grab.owner_events,
+                                          gdk_window_get_events (pointer_window),
+                                          display->pointer_grab.serial,
+                                          display->pointer_grab.time,
+                                          display->pointer_grab.implicit);
+      display->pointer_grab.converted_implicit = TRUE;
+    }
+
+  event_win = get_target_window_for_pointer_event (display,
+                                                  pointer_window,
+                                                   type,
+                                                   state);
+
+  if (event_win == NULL)
+    return TRUE;
+  
+  if (event_win != source_event->any.window)
+    {
+       event = _gdk_make_event (event_win, type, source_event, FALSE);
+
+      switch (type)
+        {
+        case GDK_BUTTON_PRESS:
+        case GDK_BUTTON_RELEASE:
+          event->button.button = source_event->button.button;
+         convert_toplevel_coords_to_window (event_win,
+                                            toplevel_x, toplevel_y,
+                                            &event->button.x, &event->button.y);
+          event->button.x_root = toplevel_x;
+          event->button.y_root = toplevel_y;
+          event->button.state = state;
+          event->button.device = source_event->button.device;
+
+         if (type == GDK_BUTTON_PRESS)
+           _gdk_event_button_generate (display, event);
+          return TRUE;
+
+        case GDK_SCROLL:
+          event->scroll.direction = source_event->scroll.direction;
+         convert_toplevel_coords_to_window (event_win,
+                                            toplevel_x, toplevel_y,
+                                            &event->scroll.x, &event->scroll.y);
+          event->scroll.x_root = toplevel_x;
+          event->scroll.y_root = toplevel_y;
+          event->scroll.state = state;
+          event->scroll.device = source_event->scroll.device;
+          return TRUE;
+
+        default:
+          return FALSE;
+        }
+    }
+  else
+    {
+      /* Same window as original window, keep the event */
+      if (source_event->type == GDK_BUTTON_PRESS)
+       _gdk_event_button_generate (display, source_event);
+      return FALSE;
+    }
+}
+
+void
+_gdk_windowing_got_event (GdkDisplay *display,
+                         GList      *event_link,
+                         GdkEvent   *event)
+{
+  GdkWindow *event_window;
+  GdkWindow *pointer_window;
+  GdkWindowObject *event_private;
+  gdouble x, y, child_x, child_y;
+  gboolean unlink_event;
+
+  event_window = event->any.window;
+  if (!event_window)
+    return;
+  
+  event_private = GDK_WINDOW_OBJECT (event_window);
+
+  if (!(is_button_type (event->type) ||
+       is_motion_type (event->type)))
+    return;
+
+  /* We should only get these events on toplevel windows */
+  g_assert (GDK_WINDOW_TYPE (event_private->parent) == GDK_WINDOW_ROOT);
+  
+  gdk_event_get_coords (event, &x, &y);
+  pointer_window = _gdk_window_find_descendant_at (event_window, x, y,
+                                                  &child_x,
+                                                  &child_y);
+  unlink_event = FALSE;
+  if (is_motion_type (event->type))
+    unlink_event = proxy_pointer_event (display,
+                                       pointer_window,
+                                       x, y,
+                                        event);
+  else if (is_button_type (event->type))
+    unlink_event = proxy_button_event (pointer_window, x, y,
+                                       event);
+
+  if (unlink_event)
+    {
+      _gdk_event_queue_remove_link (display, event_link);
+      g_list_free_1 (event_link);
+      gdk_event_free (event);
+    }
+
+
+  /* Store last pointer window and position/state */
+
+  display->pointer_info.toplevel_x = x;
+  display->pointer_info.toplevel_y = y;
+  gdk_event_get_state (event, &display->pointer_info.state);
+  
+  if (pointer_window != display->pointer_info.window_under_pointer)
+    {
+      if (display->pointer_info.window_under_pointer)
+       g_object_unref (display->pointer_info.window_under_pointer);
+      display->pointer_info.window_under_pointer = NULL;
+      if (pointer_window)
+       display->pointer_info.window_under_pointer = g_object_ref (pointer_window);
+    }
 }
 
 #define __GDK_WINDOW_C__
index 866bb694675b3115f7090c04dd89eecb88839ebd..706d768dc5bc80f7f1c78a733c497fd715b187c3 100644 (file)
 
 G_BEGIN_DECLS
 
-typedef struct _GdkGeometry           GdkGeometry;
-typedef struct _GdkWindowAttr        GdkWindowAttr;
-typedef struct _GdkPointerHooks              GdkPointerHooks;
-typedef struct _GdkWindowRedirect     GdkWindowRedirect;
+typedef struct _GdkGeometry                GdkGeometry;
+typedef struct _GdkWindowAttr              GdkWindowAttr;
+typedef struct _GdkPointerHooks            GdkPointerHooks;
+typedef struct _GdkOffscreenChildHooks     GdkOffscreenChildHooks;
+typedef struct _GdkWindowRedirect          GdkWindowRedirect;
+typedef struct _GdkWindowPaint             GdkWindowPaint;
 
 /* Classes of windows.
  *   InputOutput: Almost every window should be of this type. Such windows
@@ -77,7 +79,8 @@ typedef enum
   GDK_WINDOW_CHILD,
   GDK_WINDOW_DIALOG,
   GDK_WINDOW_TEMP,
-  GDK_WINDOW_FOREIGN
+  GDK_WINDOW_FOREIGN,
+  GDK_WINDOW_OFFSCREEN
 } GdkWindowType;
 
 /* Window attribute mask values.
@@ -248,6 +251,20 @@ struct _GdkPointerHooks
                                    gint            *win_y);
 };
 
+struct _GdkOffscreenChildHooks
+{
+  void       (*from_parent) (GdkWindow *offscreen_child,
+                            gdouble    parent_x,
+                            gdouble    parent_y,
+                            gdouble   *child_x,
+                            gdouble   *child_y);
+  void       (*to_parent)   (GdkWindow *offscreen_child,
+                            gdouble    child_x,
+                            gdouble    child_y,
+                            gdouble   *parent_x,
+                            gdouble   *parent_y);
+};
+
 typedef struct _GdkWindowObject GdkWindowObject;
 typedef struct _GdkWindowObjectClass GdkWindowObjectClass;
 
@@ -307,6 +324,19 @@ struct _GdkWindowObject
   guint update_and_descendants_freeze_count;
 
   GdkWindowRedirect *redirect;
+  const GdkOffscreenChildHooks *offscreen_hooks;
+
+  int abs_x, abs_y; /* Absolute offset in impl */
+  gint width, height;
+  GdkRegion *clip_region; /* Clip region (wrt toplevel) in window coords */
+  GdkRegion *clip_region_with_children; /* Clip region in window coords */
+  GdkColormap *colormap;
+  GdkCursor *cursor;
+  gint8 toplevel_window_type;
+
+  GdkWindowPaint *implicit_paint;
+  
+  cairo_surface_t *cairo_surface;
 };
 
 struct _GdkWindowObjectClass
@@ -645,12 +675,21 @@ GdkPointerHooks *gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks);
 
 GdkWindow *gdk_get_default_root_window (void);
 
-void gdk_window_redirect_to_drawable (GdkWindow *window,
-                                     GdkDrawable *drawable,
-                                     gint src_x, gint src_y,
-                                     gint dest_x, gint dest_y,
-                                     gint width, gint height);
-void gdk_window_remove_redirection   (GdkWindow *window);
+/* Offscreen redirection */
+GdkPixmap *gdk_window_get_offscreen_pixmap   (GdkWindow     *window);
+
+void       gdk_window_redirect_to_drawable   (GdkWindow     *window,
+                                              GdkDrawable   *drawable,
+                                              gint           src_x,
+                                              gint           src_y,
+                                              gint           dest_x,
+                                              gint           dest_y,
+                                              gint           width,
+                                              gint           height);
+void       gdk_window_remove_redirection     (GdkWindow     *window);
+
+void       gdk_window_set_offscreen_hooks    (GdkWindow                    *offscreen_window,
+                                              const GdkOffscreenChildHooks *hooks);
 
 #ifndef GDK_DISABLE_DEPRECATED
 #define GDK_ROOT_PARENT()             (gdk_get_default_root_window ())
index f9f97b6fa0d84ca5a6f8ce12fc20c1bcc46c7291..f9218b98369de93e50964e100593fa499b5848bf 100644 (file)
@@ -56,14 +56,6 @@ struct _GdkWindowImplIface
                                          gint             y,
                                          gint             width,
                                          gint             height);
-  void         (* move_region)          (GdkWindow       *window,
-                                         const GdkRegion *region,
-                                         gint             dx,
-                                         gint             dy);
-  void         (* scroll)               (GdkWindow       *window,
-                                         gint             dx,
-                                         gint             dy);
-
   void         (* clear_area)           (GdkWindow       *window,
                                          gint             x,
                                          gint             y,
@@ -73,8 +65,7 @@ struct _GdkWindowImplIface
   void         (* set_background)       (GdkWindow       *window,
                                          const GdkColor  *color);
   void         (* set_back_pixmap)      (GdkWindow       *window,
-                                         GdkPixmap       *pixmap,
-                                         gboolean         parent_relative);
+                                         GdkPixmap       *pixmap);
 
   GdkEventMask (* get_events)           (GdkWindow       *window);
   void         (* set_events)           (GdkWindow       *window,
@@ -97,9 +88,6 @@ struct _GdkWindowImplIface
   gint         (* get_origin)           (GdkWindow       *window,
                                          gint            *x,
                                          gint            *y);
-  void         (* get_offsets)          (GdkWindow       *window,
-                                         gint            *x_offset,
-                                         gint            *y_offset);
 
   void         (* shape_combine_mask)   (GdkWindow       *window,
                                          GdkBitmap       *mask,
@@ -114,11 +102,38 @@ struct _GdkWindowImplIface
 
   gboolean     (* set_static_gravities) (GdkWindow       *window,
                                         gboolean         use_static);
+
+  /* Called before processing updates for a window. This gives the windowing
+   * layer a chance to save the region for later use in avoiding duplicate
+   * exposes. The return value indicates whether the function has a saved
+   * the region; if the result is TRUE, then the windowing layer is responsible
+   * for destroying the region later.
+   */
+  gboolean     (* queue_antiexpose)     (GdkWindow       *window,
+                                        GdkRegion       *update_area);
 };
 
 /* Interface Functions */
 GType gdk_window_impl_get_type (void) G_GNUC_CONST;
 
+/* private definitions from gdkwindow.h */
+
+struct _GdkWindowRedirect
+{
+  GdkWindowObject *redirected;
+  GdkDrawable *pixmap;
+
+  gint src_x;
+  gint src_y;
+  gint dest_x;
+  gint dest_y;
+  gint width;
+  gint height;
+
+  GdkRegion *damage;
+  guint damage_idle;
+};
+
 G_END_DECLS
 
 #endif /* __GDK_WINDOW_IMPL_H__ */
index e55ff9d1aa5226a00f77b1df3d5884c3c9db9deb..a74348089da72680af9c9ad05a6efac05c5bd810 100644 (file)
@@ -137,10 +137,10 @@ data_provider_release (void *info, const void *data, size_t size)
 }
 
 GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
-               gint         width,
-               gint         height,
-               gint         depth)
+_gdk_pixmap_new (GdkDrawable *drawable,
+                 gint         width,
+                 gint         height,
+                 gint         depth)
 {
   GdkPixmap *pixmap;
   GdkDrawableImplQuartz *draw_impl;
@@ -224,10 +224,10 @@ gdk_pixmap_new (GdkDrawable *drawable,
 }
 
 GdkPixmap *
-gdk_bitmap_create_from_data (GdkDrawable *window,
-                            const gchar *data,
-                            gint         width,
-                            gint         height)
+_gdk_bitmap_create_from_data (GdkDrawable *window,
+                              const gchar *data,
+                              gint         width,
+                              gint         height)
 {
   GdkPixmap *pixmap;
   GdkPixmapImplQuartz *impl;
@@ -264,13 +264,13 @@ gdk_bitmap_create_from_data (GdkDrawable *window,
 }
 
 GdkPixmap*
-gdk_pixmap_create_from_data (GdkDrawable    *drawable,
-                            const gchar    *data,
-                            gint            width,
-                            gint            height,
-                            gint            depth,
-                            const GdkColor *fg,
-                            const GdkColor *bg)
+_gdk_pixmap_create_from_data (GdkDrawable    *drawable,
+                              const gchar    *data,
+                              gint            width,
+                              gint            height,
+                              gint            depth,
+                              const GdkColor *fg,
+                              const GdkColor *bg)
 {      
   /* FIXME: Implement */
   return NULL;
index c51a4956f2e92582ef7dc003422ecafc82e5276e..37199c38879f03ac4aa0f298e69e14d509ed3d67 100644 (file)
@@ -600,7 +600,7 @@ _gdk_x11_display_is_root_window (GdkDisplay *display,
  */
 void
 gdk_display_pointer_ungrab (GdkDisplay *display,
-                           guint32     time)
+                           guint32     time_)
 {
   Display *xdisplay;
   GdkDisplayX11 *display_x11;
@@ -610,33 +610,19 @@ gdk_display_pointer_ungrab (GdkDisplay *display,
   display_x11 = GDK_DISPLAY_X11 (display);
   xdisplay = GDK_DISPLAY_XDISPLAY (display);
   
-  _gdk_input_ungrab_pointer (display, time);
-  XUngrabPointer (xdisplay, time);
+  _gdk_input_ungrab_pointer (display, time_);
+  XUngrabPointer (xdisplay, time_);
   XFlush (xdisplay);
 
-  if (time == GDK_CURRENT_TIME || 
-      display_x11->pointer_xgrab_time == GDK_CURRENT_TIME ||
-      !XSERVER_TIME_IS_LATER (display_x11->pointer_xgrab_time, time))
-    display_x11->pointer_xgrab_window = NULL;
-}
-
-/**
- * gdk_display_pointer_is_grabbed:
- * @display: a #GdkDisplay
- *
- * Test if the pointer is grabbed.
- *
- * Returns: %TRUE if an active X pointer grab is in effect
- *
- * Since: 2.2
- */
-gboolean
-gdk_display_pointer_is_grabbed (GdkDisplay *display)
-{
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
-  
-  return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL &&
-         !GDK_DISPLAY_X11 (display)->pointer_xgrab_implicit);
+  if (time_ == GDK_CURRENT_TIME ||
+      display->pointer_grab.time == GDK_CURRENT_TIME ||
+      !XSERVER_TIME_IS_LATER (display->pointer_grab.time, time_))
+    {
+      _gdk_display_unset_has_pointer_grab (display,
+                                          FALSE,
+                                          FALSE,
+                                          time_);
+    }
 }
 
 /**
@@ -1335,7 +1321,9 @@ gdk_display_store_clipboard (GdkDisplay    *display,
 {
   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
   Atom clipboard_manager, save_targets;
-  
+
+  g_return_if_fail (GDK_WINDOW_IS_X11 (clipboard_window));
+
   clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
   save_targets = gdk_x11_get_xatom_by_name_for_display (display, "SAVE_TARGETS");
 
index 0ade8f08355e4a66adf0635cfb189c12d7fcbf35..619a1ad8fdad8205a62676ab27b58d8b9a5349c3 100644 (file)
@@ -30,6 +30,7 @@
 #include <gdk/gdkdisplay.h>
 #include <gdk/gdkkeys.h>
 #include <gdk/gdkwindow.h>
+#include <gdk/gdkinternals.h>
 #include <gdk/gdk.h>           /* For gdk_get_program_class() */
 
 G_BEGIN_DECLS
@@ -93,17 +94,14 @@ struct _GdkDisplayX11
    * (grabs, properties etc.) Otherwise always TRUE. */
   gboolean trusted_client;
 
-  /* Information about current pointer and keyboard grabs held by this
-   * client. If gdk_pointer_xgrab_window or gdk_keyboard_xgrab_window
+  /* Information about current keyboard grabs held by this
+   * client. If gdk_keyboard_xgrab_window
    * window is NULL, then the other associated fields are ignored
+   * Pointer grab info is stored in GdkDisplay.
    */
-  GdkWindowObject *pointer_xgrab_window;
-  gulong pointer_xgrab_serial;
-  gboolean pointer_xgrab_owner_events;
-  gboolean pointer_xgrab_implicit;
-  guint32 pointer_xgrab_time;
 
   GdkWindowObject *keyboard_xgrab_window;
+  GdkWindowObject *keyboard_xgrab_native_window;
   gulong keyboard_xgrab_serial;
   gboolean keyboard_xgrab_owner_events;
   guint32 keyboard_xgrab_time;
@@ -169,6 +167,9 @@ struct _GdkDisplayX11
 
   /* Alpha mask picture format */
   XRenderPictFormat *mask_format;
+
+  /* The offscreen window that has the pointer in it (if any) */
+  GdkWindow *active_offscreen_window;
 };
 
 struct _GdkDisplayX11Class
index 942ad91eb9b33f5088208752960f254f7647cc0a..a43bac0e5f10cfafafd9b074383c41a489844e62 100644 (file)
@@ -2987,6 +2987,7 @@ gdk_drag_begin (GdkWindow     *window,
   GdkDragContext *new_context;
   
   g_return_val_if_fail (window != NULL, NULL);
+  g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), NULL);
 
   new_context = gdk_drag_context_new ();
   new_context->is_source = TRUE;
@@ -3192,7 +3193,7 @@ gdk_drag_find_window_for_screen (GdkDragContext  *context,
   window_cache = drag_context_find_window_cache (context, screen);
 
   dest = get_client_window_at_coords (window_cache,
-                                     drag_window ? 
+                                     drag_window && GDK_WINDOW_IS_X11 (drag_window) 
                                      GDK_DRAWABLE_XID (drag_window) : None,
                                      x_root, y_root);
 
@@ -3262,6 +3263,7 @@ gdk_drag_motion (GdkDragContext *context,
   GdkDragContextPrivateX11 *private = PRIVATE_DATA (context);
 
   g_return_val_if_fail (context != NULL, FALSE);
+  g_return_val_if_fail (dest_window == NULL || GDK_WINDOW_IS_X11 (dest_window), FALSE);
 
   private->old_actions = context->actions;
   context->actions = possible_actions;
index a19c7a2e2cc473b9441fe983b081cd49c28cde3e..1c405687ad5734fcff31635e54cb84394ed0ebdf 100644 (file)
@@ -870,7 +870,17 @@ gdk_x11_drawable_get_xid (GdkDrawable *drawable)
   GdkDrawable *impl;
   
   if (GDK_IS_WINDOW (drawable))
-    impl = ((GdkPixmapObject *)drawable)->impl;
+    {
+      if (!GDK_WINDOW_IS_X11 (drawable))
+        {
+         /* TODO: At this point we could convert a virtual window
+            to a native one (unless its in an offscreen window) */
+          g_warning (G_STRLOC " drawable is not a native X11 window");
+          return None;
+        }
+
+      impl = ((GdkPixmapObject *)drawable)->impl;
+    }
   else if (GDK_IS_PIXMAP (drawable))
     impl = ((GdkPixmapObject *)drawable)->impl;
   else
@@ -1447,6 +1457,45 @@ gdk_x11_cairo_surface_destroy (void *data)
   impl->cairo_surface = NULL;
 }
 
+void
+_gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+                                      int width,
+                                      int height)
+{
+  cairo_xlib_surface_set_size (surface, width, height);
+}
+
+cairo_surface_t *
+_gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+                                    int width,
+                                    int height)
+{
+  GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+  GdkVisual *visual;
+    
+  visual = gdk_drawable_get_visual (drawable);
+  if (visual) 
+    return cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
+                                     impl->xid,
+                                     GDK_VISUAL_XVISUAL (visual),
+                                     width, height);
+  else if (gdk_drawable_get_depth (drawable) == 1)
+    return cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
+                                                   impl->xid,
+                                                   GDK_SCREEN_XSCREEN (impl->screen),
+                                                   width, height);
+  else
+    {
+      g_warning ("Using Cairo rendering requires the drawable argument to\n"
+                "have a specified colormap. All windows have a colormap,\n"
+                "however, pixmaps only have colormap by default if they\n"
+                "were created with a non-NULL window argument. Otherwise\n"
+                "a colormap must be set on them with gdk_drawable_set_colormap");
+      return NULL;
+    }
+  
+}
+
 static cairo_surface_t *
 gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
 {
@@ -1458,35 +1507,15 @@ gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
 
   if (!impl->cairo_surface)
     {
-      GdkVisual *visual = NULL;
       int width, height;
   
-      visual = gdk_drawable_get_visual (drawable);
-
       gdk_drawable_get_size (drawable, &width, &height);
 
-      if (visual) 
-       impl->cairo_surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
-                                                        impl->xid,
-                                                        GDK_VISUAL_XVISUAL (visual),
-                                                        width, height);
-      else if (gdk_drawable_get_depth (drawable) == 1)
-       impl->cairo_surface = cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
-                                                                   impl->xid,
-                                                                   GDK_SCREEN_XSCREEN (impl->screen),
-                                                                   width, height);
-      else
-       {
-         g_warning ("Using Cairo rendering requires the drawable argument to\n"
-                    "have a specified colormap. All windows have a colormap,\n"
-                    "however, pixmaps only have colormap by default if they\n"
-                    "were created with a non-NULL window argument. Otherwise\n"
-                    "a colormap must be set on them with gdk_drawable_set_colormap");
-         return NULL;
-       }
-
-      cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
-                                  drawable, gdk_x11_cairo_surface_destroy);
+      impl->cairo_surface = _gdk_windowing_create_cairo_surface (drawable, width, height);
+      
+      if (impl->cairo_surface)
+       cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
+                                    drawable, gdk_x11_cairo_surface_destroy);
     }
   else
     cairo_surface_reference (impl->cairo_surface);
index 096c17005c141cf26122b85dc9b1d0f096e2e5c6..b2a438c2811c79ddbbebb88ea7f31131cc29ba15 100644 (file)
@@ -313,7 +313,7 @@ gdk_event_get_graphics_expose (GdkWindow *window)
   GdkEvent *event;
   
   g_return_val_if_fail (window != NULL, NULL);
-  
+
   XIfEvent (GDK_WINDOW_XDISPLAY (window), &xevent, 
            graphics_expose_predicate, (XPointer) window);
   
@@ -879,7 +879,6 @@ gdk_event_translate (GdkDisplay *display,
   GdkWindow *filter_window;
   GdkWindowImplX11 *window_impl = NULL;
   gboolean return_val;
-  gint xoffset, yoffset;
   GdkScreen *screen = NULL;
   GdkScreenX11 *screen_x11 = NULL;
   GdkToplevelX11 *toplevel = NULL;
@@ -942,6 +941,14 @@ gdk_event_translate (GdkDisplay *display,
     
   if (window != NULL)
     {
+      /* Rewrite keyboard grabs to offscreen windows */
+      if ((xevent->type == KeyPress || xevent->type == KeyRelease) &&
+          window_private == display_x11->keyboard_xgrab_native_window)
+        {
+          window_private = display_x11->keyboard_xgrab_window;
+          window = (GdkWindow *) window_private;
+        }
+
       window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
       
       /* Move key events on focus window to the real toplevel, and
@@ -1041,16 +1048,6 @@ gdk_event_translate (GdkDisplay *display,
 
   return_val = TRUE;
 
-  if (window)
-    {
-      _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-    }
-  else
-    {
-      xoffset = 0;
-      yoffset = 0;
-    }
-
   switch (xevent->type)
     {
     case KeyPress:
@@ -1129,8 +1126,8 @@ gdk_event_translate (GdkDisplay *display,
 
          event->scroll.window = window;
          event->scroll.time = xevent->xbutton.time;
-         event->scroll.x = xevent->xbutton.x + xoffset;
-         event->scroll.y = xevent->xbutton.y + yoffset;
+         event->scroll.x = xevent->xbutton.x;
+         event->scroll.y = xevent->xbutton.y;
          event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
          event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
          event->scroll.state = (GdkModifierType) xevent->xbutton.state;
@@ -1148,8 +1145,8 @@ gdk_event_translate (GdkDisplay *display,
          event->button.type = GDK_BUTTON_PRESS;
          event->button.window = window;
          event->button.time = xevent->xbutton.time;
-         event->button.x = xevent->xbutton.x + xoffset;
-         event->button.y = xevent->xbutton.y + yoffset;
+         event->button.x = xevent->xbutton.x;
+         event->button.y = xevent->xbutton.y;
          event->button.x_root = (gfloat)xevent->xbutton.x_root;
          event->button.y_root = (gfloat)xevent->xbutton.y_root;
          event->button.axes = NULL;
@@ -1162,8 +1159,6 @@ gdk_event_translate (GdkDisplay *display,
              return_val = FALSE;
              break;
            }
-
-         _gdk_event_button_generate (display, event);
           break;
        }
 
@@ -1192,14 +1187,14 @@ gdk_event_translate (GdkDisplay *display,
           xevent->xbutton.button == 6 || xevent->xbutton.button ==7)
        {
          return_val = FALSE;
-         break;
+         goto release_out;
        }
 
       event->button.type = GDK_BUTTON_RELEASE;
       event->button.window = window;
       event->button.time = xevent->xbutton.time;
-      event->button.x = xevent->xbutton.x + xoffset;
-      event->button.y = xevent->xbutton.y + yoffset;
+      event->button.x = xevent->xbutton.x;
+      event->button.y = xevent->xbutton.y;
       event->button.x_root = (gfloat)xevent->xbutton.x_root;
       event->button.y_root = (gfloat)xevent->xbutton.y_root;
       event->button.axes = NULL;
@@ -1210,9 +1205,10 @@ gdk_event_translate (GdkDisplay *display,
       if (!set_screen_from_root (display, event, xevent->xbutton.root))
        {
          return_val = FALSE;
-         break;
+         goto release_out;
        }
-
+      
+    release_out:
       _gdk_xgrab_check_button_event (window, xevent);
       break;
       
@@ -1234,8 +1230,8 @@ gdk_event_translate (GdkDisplay *display,
       event->motion.type = GDK_MOTION_NOTIFY;
       event->motion.window = window;
       event->motion.time = xevent->xmotion.time;
-      event->motion.x = xevent->xmotion.x + xoffset;
-      event->motion.y = xevent->xmotion.y + yoffset;
+      event->motion.x = xevent->xmotion.x;
+      event->motion.y = xevent->xmotion.y;
       event->motion.x_root = (gfloat)xevent->xmotion.x_root;
       event->motion.y_root = (gfloat)xevent->xmotion.y_root;
       event->motion.axes = NULL;
@@ -1304,8 +1300,8 @@ gdk_event_translate (GdkDisplay *display,
        event->crossing.subwindow = NULL;
       
       event->crossing.time = xevent->xcrossing.time;
-      event->crossing.x = xevent->xcrossing.x + xoffset;
-      event->crossing.y = xevent->xcrossing.y + yoffset;
+      event->crossing.x = xevent->xcrossing.x;
+      event->crossing.y = xevent->xcrossing.y;
       event->crossing.x_root = xevent->xcrossing.x_root;
       event->crossing.y_root = xevent->xcrossing.y_root;
       
@@ -1399,8 +1395,8 @@ gdk_event_translate (GdkDisplay *display,
        event->crossing.subwindow = NULL;
       
       event->crossing.time = xevent->xcrossing.time;
-      event->crossing.x = xevent->xcrossing.x + xoffset;
-      event->crossing.y = xevent->xcrossing.y + yoffset;
+      event->crossing.x = xevent->xcrossing.x;
+      event->crossing.y = xevent->xcrossing.y;
       event->crossing.x_root = xevent->xcrossing.x_root;
       event->crossing.y_root = xevent->xcrossing.y_root;
       
@@ -1596,8 +1592,8 @@ gdk_event_translate (GdkDisplay *display,
       {
        GdkRectangle expose_rect;
 
-       expose_rect.x = xevent->xexpose.x + xoffset;
-       expose_rect.y = xevent->xexpose.y + yoffset;
+       expose_rect.x = xevent->xexpose.x;
+       expose_rect.y = xevent->xexpose.y;
        expose_rect.width = xevent->xexpose.width;
        expose_rect.height = xevent->xexpose.height;
 
@@ -1636,8 +1632,8 @@ gdk_event_translate (GdkDisplay *display,
             break;
           }
         
-       expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
-       expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
+       expose_rect.x = xevent->xgraphicsexpose.x;
+       expose_rect.y = xevent->xgraphicsexpose.y;
        expose_rect.width = xevent->xgraphicsexpose.width;
        expose_rect.height = xevent->xgraphicsexpose.height;
            
@@ -1826,9 +1822,9 @@ gdk_event_translate (GdkDisplay *display,
                           : ""));
       if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
         { 
-         window_impl->width = xevent->xconfigure.width;
-         window_impl->height = xevent->xconfigure.height;
-         
+         window_private->width = xevent->xconfigure.width;
+         window_private->height = xevent->xconfigure.height;
+
          _gdk_x11_drawable_update_size (window_private->impl);
          _gdk_x11_screen_size_changed (screen, xevent);
         }
@@ -1887,9 +1883,10 @@ gdk_event_translate (GdkDisplay *display,
            }
          window_private->x = event->configure.x;
          window_private->y = event->configure.y;
-         window_impl->width = xevent->xconfigure.width;
-         window_impl->height = xevent->xconfigure.height;
+         window_private->width = xevent->xconfigure.width;
+         window_private->height = xevent->xconfigure.height;
          
+         _gdk_window_update_size (window);
          _gdk_x11_drawable_update_size (window_private->impl);
          
          if (window_private->resize_count >= 1)
@@ -2298,6 +2295,7 @@ _gdk_events_queue (GdkDisplay *display)
       if (gdk_event_translate (display, event, &xevent, FALSE))
        {
          ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+          _gdk_windowing_got_event (display, node, event);
        }
       else
        {
index 8c3e3407194239da741f997d41222c6870c3a2a7..0a6869a2155547fa7180e07d1952f22549c54d9d 100644 (file)
@@ -608,7 +608,8 @@ gdk_x11_gc_values_to_xvalues (GdkGCValues    *values,
 
 void
 _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
-                                  const GdkRegion *region)
+                                  const GdkRegion *region,
+                                  gboolean reset_origin)
 {
   GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
 
@@ -623,8 +624,11 @@ _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
 
   x11_gc->have_clip_region = region != NULL;
 
-  gc->clip_x_origin = 0;
-  gc->clip_y_origin = 0;
+  if (reset_origin)
+    {
+      gc->clip_x_origin = 0;
+      gc->clip_y_origin = 0;
+    }
 
   x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
 }
index 9271f090d581b42ab62f42ab3728facc5236bcb6..47f210bbcfcde2e21acc326d5bda8df96e6353b9 100644 (file)
@@ -165,170 +165,13 @@ struct _GdkWindowQueueItem
   } u;
 };
 
-struct _GdkWindowParentPos
-{
-  gint x;
-  gint y;
-  gint x11_x;
-  gint x11_y;
-  GdkRectangle clip_rect;
-};
-
-static void gdk_window_compute_position   (GdkWindowImplX11      *window,
-                                          GdkWindowParentPos *parent_pos,
-                                          GdkXPositionInfo   *info);
-static void gdk_window_compute_parent_pos (GdkWindowImplX11      *window,
-                                          GdkWindowParentPos *parent_pos);
-static void gdk_window_premove            (GdkWindow          *window,
-                                          GdkWindowParentPos *parent_pos);
-static void gdk_window_postmove           (GdkWindow          *window,
-                                          GdkWindowParentPos *parent_pos);
-static void gdk_window_queue_translation  (GdkWindow          *window,
-                                          GdkRegion          *area,
-                                          gint                dx,
-                                          gint                dy);
-static void gdk_window_clip_changed       (GdkWindow          *window,
-                                          GdkRectangle       *old_clip,
-                                          GdkRectangle       *new_clip);
-
-void
-_gdk_x11_window_get_offsets (GdkWindow *window,
-                             gint      *x_offset,
-                             gint      *y_offset)
-{
-  GdkWindowImplX11 *impl =
-    GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
-
-  *x_offset = impl->position_info.x_offset;
-  *y_offset = impl->position_info.y_offset;
-}
-
-void
-_gdk_window_init_position (GdkWindow *window)
-{
-  GdkWindowParentPos parent_pos;
-  GdkWindowImplX11 *impl;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  impl =
-    GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
-  
-  gdk_window_compute_parent_pos (impl, &parent_pos);
-  gdk_window_compute_position (impl, &parent_pos, &impl->position_info);
-}
-
-static void
-gdk_window_copy_area_scroll (GdkWindow    *window,
-                            GdkRectangle *dest_rect,
-                            gint          dx,
-                            gint          dy)
-{
-  GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
-  GList *l;
-
-  if (dest_rect->width > 0 && dest_rect->height > 0)
-    {
-      GdkGC *gc;
-
-      gc = _gdk_drawable_get_scratch_gc (window, TRUE);
-      
-      gdk_window_queue_translation (window, NULL, dx, dy);
-   
-      XCopyArea (GDK_WINDOW_XDISPLAY (window),
-                GDK_WINDOW_XID (window),
-                GDK_WINDOW_XID (window),
-                gdk_x11_gc_get_xgc (gc),
-                dest_rect->x - dx, dest_rect->y - dy,
-                dest_rect->width, dest_rect->height,
-                dest_rect->x, dest_rect->y);
-    }
-
-  for (l = obj->children; l; l = l->next)
-    {
-      GdkWindow *child = (GdkWindow*) l->data;
-      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
-
-      gdk_window_move (child, child_obj->x + dx, child_obj->y + dy);
-    }
-}
-
-static void
-compute_intermediate_position (GdkXPositionInfo *position_info,
-                              GdkXPositionInfo *new_info,
-                              gint              d_xoffset,
-                              gint              d_yoffset,
-                              GdkRectangle     *new_position)
-{
-  gint new_x0, new_x1, new_y0, new_y1;
-  
-  /* Wrap d_xoffset, d_yoffset into [-32768,32767] range. For the
-   * purposes of subwindow movement, it doesn't matter if we are
-   * off by a factor of 65536, and if we don't do this range
-   * reduction, we'll end up with invalid widths.
-   */
-  d_xoffset = (gint16)d_xoffset;
-  d_yoffset = (gint16)d_yoffset;
-  
-  if (d_xoffset < 0)
-    {
-      new_x0 = position_info->x + d_xoffset;
-      new_x1 = position_info->x + position_info->width;
-    }
-  else
-    {
-      new_x0 = position_info->x;
-      new_x1 = position_info->x + new_info->width + d_xoffset;
-    }
-
-  new_position->x = new_x0;
-  new_position->width = new_x1 - new_x0;
-  
-  if (d_yoffset < 0)
-    {
-      new_y0 = position_info->y + d_yoffset;
-      new_y1 = position_info->y + position_info->height;
-    }
-  else
-    {
-      new_y0 = position_info->y;
-      new_y1 = position_info->y + new_info->height + d_yoffset;
-    }
-  
-  new_position->y = new_y0;
-  new_position->height = new_y1 - new_y0;
-}
-
 static void
-translate_pos (GdkWindowParentPos *dest, GdkWindowParentPos *src,
-               GdkWindowObject *obj, GdkXPositionInfo *pos_info,
-               gboolean set_clip)
-{
-  dest->x = src->x + obj->x;
-  dest->y = src->y + obj->y;
-  dest->x11_x = src->x11_x + pos_info->x;
-  dest->x11_y = src->x11_y + pos_info->y;
-
-  if (set_clip)
-      dest->clip_rect = pos_info->clip_rect;
-}
-
-static void
-move (GdkWindow *window, GdkXPositionInfo *pos)
+move (GdkWindow *window, GdkRectangle *pos)
 {
   XMoveWindow (GDK_WINDOW_XDISPLAY (window),
                GDK_WINDOW_XID (window), pos->x, pos->y);
 }
 
-static void
-move_relative (GdkWindow *window, GdkRectangle *rect,
-               gint dx, gint dy)
-{
-  XMoveWindow (GDK_WINDOW_XDISPLAY (window),
-               GDK_WINDOW_XID (window),
-               rect->x + dx, rect->y + dy);
-}
-
 static void
 move_resize (GdkWindow *window, GdkRectangle *pos)
 {
@@ -337,245 +180,6 @@ move_resize (GdkWindow *window, GdkRectangle *pos)
                      pos->x, pos->y, pos->width, pos->height);
 }
 
-static void
-gdk_window_guffaw_scroll (GdkWindow    *window,
-                         gint          dx,
-                         gint          dy)
-{
-  GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
-  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
-  gint d_xoffset = -dx;
-  gint d_yoffset = -dy;
-  GdkRectangle new_position;
-  GdkXPositionInfo new_info;
-  GdkWindowParentPos parent_pos;
-  GList *l;
-  
-  gdk_window_compute_parent_pos (impl, &parent_pos);
-  gdk_window_compute_position (impl, &parent_pos, &new_info);
-
-  translate_pos (&parent_pos, &parent_pos, obj, &new_info, TRUE);
-
-  _gdk_x11_window_tmp_unset_bg (window, FALSE);;
-
-  if (dx > 0 || dy > 0)
-    gdk_window_queue_translation (window, NULL, MAX (dx, 0), MAX (dy, 0));
-       
-  gdk_window_set_static_gravities (window, TRUE);
-
-  compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
-                                &new_position);
-  
-  move_resize (window, &new_position);
-  
-  for (l = obj->children; l; l = l->next)
-    {
-      GdkWindow *child = (GdkWindow*) l->data;
-      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
-
-      child_obj->x -= d_xoffset;
-      child_obj->y -= d_yoffset;
-
-      gdk_window_premove (child, &parent_pos);
-    }
-  
-  move_relative (window, &new_position, -d_xoffset, -d_yoffset);
-  
-  if (dx < 0 || dy < 0)
-    gdk_window_queue_translation (window, NULL, MIN (dx, 0), MIN (dy, 0));
-  
-  move_resize (window, (GdkRectangle *) &impl->position_info);
-  
-  if (impl->position_info.no_bg)
-    _gdk_x11_window_tmp_reset_bg (window, FALSE);
-  
-  impl->position_info = new_info;
-  
-  g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
-}
-
-void
-_gdk_x11_window_scroll (GdkWindow *window,
-                        gint       dx,
-                        gint       dy)
-{
-  gboolean can_guffaw_scroll = FALSE;
-  GdkRegion *invalidate_region;
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *obj;
-  GdkRectangle src_rect, dest_rect;
-  
-  obj = GDK_WINDOW_OBJECT (window);
-  impl = GDK_WINDOW_IMPL_X11 (obj->impl);  
-
-  /* Move the current invalid region */
-  if (obj->update_area)
-    gdk_region_offset (obj->update_area, dx, dy);
-  
-  /* impl->position_info.clip_rect isn't meaningful for toplevels */
-  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
-    src_rect = impl->position_info.clip_rect;
-  else
-    {
-      src_rect.x = 0;
-      src_rect.y = 0;
-      src_rect.width = impl->width;
-      src_rect.height = impl->height;
-    }
-  
-  invalidate_region = gdk_region_rectangle (&src_rect);
-
-  dest_rect = src_rect;
-  dest_rect.x += dx;
-  dest_rect.y += dy;
-  gdk_rectangle_intersect (&dest_rect, &src_rect, &dest_rect);
-
-  if (dest_rect.width > 0 && dest_rect.height > 0)
-    {
-      GdkRegion *tmp_region;
-
-      tmp_region = gdk_region_rectangle (&dest_rect);
-      gdk_region_subtract (invalidate_region, tmp_region);
-      gdk_region_destroy (tmp_region);
-    }
-  
-  gdk_window_invalidate_region (window, invalidate_region, TRUE);
-  gdk_region_destroy (invalidate_region);
-
-  /* We can guffaw scroll if we are a child window, and the parent
-   * does not extend beyond our edges. Otherwise, we use XCopyArea, then
-   * move any children later
-   */
-  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
-    {
-      GdkWindowImplX11 *parent_impl = GDK_WINDOW_IMPL_X11 (obj->parent->impl);  
-      can_guffaw_scroll = ((dx == 0 || (obj->x <= 0 && obj->x + impl->width >= parent_impl->width)) &&
-                          (dy == 0 || (obj->y <= 0 && obj->y + impl->height >= parent_impl->height)));
-    }
-
-  if (!obj->children || !can_guffaw_scroll)
-    gdk_window_copy_area_scroll (window, &dest_rect, dx, dy);
-  else
-    gdk_window_guffaw_scroll (window, dx, dy);
-}
-
-void
-_gdk_x11_window_move_region (GdkWindow       *window,
-                             const GdkRegion *region,
-                             gint             dx,
-                             gint             dy)
-{
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *private;
-  GdkRegion *window_clip;
-  GdkRegion *src_region;
-  GdkRegion *brought_in;
-  GdkRegion *dest_region;
-  GdkRegion *moving_invalid_region;
-  GdkRectangle dest_extents;
-  GdkGC *gc;
-  
-  private = GDK_WINDOW_OBJECT (window);
-  impl = GDK_WINDOW_IMPL_X11 (private->impl);  
-
-  window_clip = gdk_region_rectangle (&impl->position_info.clip_rect);
-
-  /* compute source regions */
-  src_region = gdk_region_copy (region);
-  brought_in = gdk_region_copy (region);
-  gdk_region_intersect (src_region, window_clip);
-
-  gdk_region_subtract (brought_in, src_region);
-  gdk_region_offset (brought_in, dx, dy);
-
-  /* compute destination regions */
-  dest_region = gdk_region_copy (src_region);
-  gdk_region_offset (dest_region, dx, dy);
-  gdk_region_intersect (dest_region, window_clip);
-  gdk_region_get_clipbox (dest_region, &dest_extents);
-
-  gdk_region_destroy (window_clip);
-
-  /* calculating moving part of current invalid area */
-  moving_invalid_region = NULL;
-  if (private->update_area)
-    {
-      moving_invalid_region = gdk_region_copy (private->update_area);
-      gdk_region_intersect (moving_invalid_region, src_region);
-      gdk_region_offset (moving_invalid_region, dx, dy);
-    }
-  
-  /* invalidate all of the src region */
-  gdk_window_invalidate_region (window, src_region, FALSE);
-
-  /* un-invalidate destination region */
-  if (private->update_area)
-    gdk_region_subtract (private->update_area, dest_region);
-  
-  /* invalidate moving parts of existing update area */
-  if (moving_invalid_region)
-    {
-      gdk_window_invalidate_region (window, moving_invalid_region, FALSE);
-      gdk_region_destroy (moving_invalid_region);
-    }
-
-  /* invalidate area brought in from off-screen */
-  gdk_window_invalidate_region (window, brought_in, FALSE);
-  gdk_region_destroy (brought_in);
-
-  /* Actually do the moving */
-  gdk_window_queue_translation (window, src_region, dx, dy);
-
-  gc = _gdk_drawable_get_scratch_gc (window, TRUE);
-  gdk_gc_set_clip_region (gc, dest_region);
-  
-  XCopyArea (GDK_WINDOW_XDISPLAY (window),
-            GDK_WINDOW_XID (window),
-            GDK_WINDOW_XID (window),
-            GDK_GC_XGC (gc),
-            dest_extents.x - dx, dest_extents.y - dy,
-            dest_extents.width, dest_extents.height,
-            dest_extents.x, dest_extents.y);
-
-  /* Unset clip region of cached GC */
-  gdk_gc_set_clip_region (gc, NULL);
-  
-  gdk_region_destroy (src_region);
-  gdk_region_destroy (dest_region);
-}
-
-static void
-reset_backgrounds (GdkWindow *window)
-{
-  GdkWindowObject *obj = (GdkWindowObject *)window;
-
-  _gdk_x11_window_tmp_reset_bg (window, FALSE);
-  
-  if (obj->parent)
-    _gdk_x11_window_tmp_reset_bg ((GdkWindow *)obj->parent, FALSE);
-}
-
-static void
-map_if_needed (GdkWindow *window, GdkXPositionInfo *pos_info)
-{
-  GdkWindowObject *obj = (GdkWindowObject *) window;
-  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
-  if (!impl->position_info.mapped && pos_info->mapped && GDK_WINDOW_IS_MAPPED (obj))
-    XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
-}
-
-static void
-unmap_if_needed (GdkWindow *window, GdkXPositionInfo *pos_info)
-{
-  GdkWindowObject *obj = (GdkWindowObject *) window;
-  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
-  if (impl->position_info.mapped && !pos_info->mapped)
-    XUnmapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
-}
-
 void
 _gdk_window_move_resize_child (GdkWindow *window,
                               gint       x,
@@ -585,16 +189,12 @@ _gdk_window_move_resize_child (GdkWindow *window,
 {
   GdkWindowImplX11 *impl;
   GdkWindowObject *obj;
-  GdkXPositionInfo new_info;
-  GdkWindowParentPos parent_pos;
+  GdkRectangle new_info;
   
-  gint d_xoffset, d_yoffset;
   gint dx, dy;
   gboolean is_move;
   gboolean is_resize;
 
-  GdkRectangle old_pos;
-  
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window)); 
 
@@ -605,321 +205,27 @@ _gdk_window_move_resize_child (GdkWindow *window,
   dy = y - obj->y;
   
   is_move = dx != 0 || dy != 0;
-  is_resize = impl->width != width || impl->height != height;
+  is_resize = obj->width != width || obj->height != height;
 
+#if 0 /* Not right, doesn't take abs_x/y into consideration */
   if (!is_move && !is_resize)
     return;
+#endif
   
-  old_pos.x = obj->x;
-  old_pos.y = obj->y;
-  old_pos.width = impl->width;
-  old_pos.height = impl->height;
-
   obj->x = x;
   obj->y = y;
-  impl->width = width;
-  impl->height = height;
-
-  gdk_window_compute_parent_pos (impl, &parent_pos);
-  gdk_window_compute_position (impl, &parent_pos, &new_info);
-
-  gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
-
-  translate_pos (&parent_pos, &parent_pos, obj, &new_info, TRUE);
-
-  d_xoffset = new_info.x_offset - impl->position_info.x_offset;
-  d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-  
-  if (d_xoffset != 0 || d_yoffset != 0)
-    {
-      GdkRectangle new_position;
-
-      gdk_window_set_static_gravities (window, TRUE);
-
-      if (d_xoffset < 0 || d_yoffset < 0)
-       gdk_window_queue_translation (window, NULL, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-
-      compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
-                                    &new_position);
-      
-      move_resize (window, &new_position);
-      
-      g_list_foreach (obj->children, (GFunc) gdk_window_premove, &parent_pos);
-
-      move_relative (window, &new_position, dx, dy);
-      
-      if (d_xoffset > 0 || d_yoffset > 0)
-       gdk_window_queue_translation (window, NULL, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
-      
-      move_resize (window, (GdkRectangle *) &new_info);
-
-      reset_backgrounds (window);
-
-      map_if_needed (window, &new_info);
-      
-      impl->position_info = new_info;
-      
-      g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
-    }
-  else
-    {
-      if (is_move && is_resize)
-       gdk_window_set_static_gravities (window, FALSE);
-
-      unmap_if_needed (window, &new_info);
-      
-      g_list_foreach (obj->children, (GFunc) gdk_window_premove, &parent_pos);
-
-      if (is_resize)
-          move_resize (window, (GdkRectangle *) &new_info);
-      else
-          move (window, &new_info);
-
-      g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
-
-      reset_backgrounds (window);
-      
-      map_if_needed (window, &new_info);
-
-      impl->position_info = new_info;
-    }
-
-  if (GDK_WINDOW_IS_MAPPED (obj) && obj->parent && !obj->input_only)
-    gdk_window_invalidate_rect ((GdkWindow *)obj->parent, &old_pos, FALSE);
-}
-
-static void
-gdk_window_compute_position (GdkWindowImplX11   *window,
-                            GdkWindowParentPos *parent_pos,
-                            GdkXPositionInfo   *info)
-{
-  GdkWindowObject *wrapper;
-  int parent_x_offset;
-  int parent_y_offset;
-
-  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (window));
+  obj->width = width;
+  obj->height = height;
 
-  wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_X11 (window)->wrapper);
-  
-  info->big = FALSE;
+  new_info.x = obj->x + obj->parent->abs_x;
+  new_info.y = obj->y + obj->parent->abs_y;
+  new_info.width = obj->width;
+  new_info.height = obj->height;
   
-  if (window->width <= 32767)
-    {
-      info->width = window->width;
-      info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
-    }
+  if (is_resize)
+    move_resize (window, &new_info);
   else
-    {
-      info->big = TRUE;
-      info->width = 32767;
-      if (parent_pos->x + wrapper->x < -16384)
-       {
-         if (parent_pos->x + wrapper->x + window->width < 16384)
-           info->x = parent_pos->x + wrapper->x + window->width - info->width - parent_pos->x11_x;
-         else
-           info->x = -16384 - parent_pos->x11_x;
-       }
-      else
-       info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
-    }
-
-  if (window->height <= 32767)
-    {
-      info->height = window->height;
-      info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
-    }
-  else
-    {
-      info->big = TRUE;
-      info->height = 32767;
-      if (parent_pos->y + wrapper->y < -16384)
-       {
-         if (parent_pos->y + wrapper->y + window->height < 16384)
-           info->y = parent_pos->y + wrapper->y + window->height - info->height - parent_pos->x11_y;
-         else
-           info->y = -16384 - parent_pos->x11_y;
-       }
-      else
-       info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
-    }
-
-  parent_x_offset = parent_pos->x11_x - parent_pos->x;
-  parent_y_offset = parent_pos->x11_y - parent_pos->y;
-  
-  info->x_offset = parent_x_offset + info->x - wrapper->x;
-  info->y_offset = parent_y_offset + info->y - wrapper->y;
-
-  /* We don't considering the clipping of toplevel windows and their immediate children
-   * by their parents, and simply always map those windows.
-   */
-  if (parent_pos->clip_rect.width == G_MAXINT)
-    info->mapped = TRUE;
-  /* Check if the window would wrap around into the visible space in either direction */
-  else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
-      info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
-      info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
-      info->y + info->height + parent_y_offset  > parent_pos->clip_rect.y + 65536)
-    info->mapped = FALSE;
-  else
-    info->mapped = TRUE;
-
-  info->no_bg = FALSE;
-
-  if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
-    {
-      info->clip_rect.x = wrapper->x;
-      info->clip_rect.y = wrapper->y;
-      info->clip_rect.width = window->width;
-      info->clip_rect.height = window->height;
-      
-      gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
-
-      info->clip_rect.x -= wrapper->x;
-      info->clip_rect.y -= wrapper->y;
-    }
-  else
-    {
-      info->clip_rect.x = 0;
-      info->clip_rect.y = 0;
-      info->clip_rect.width = G_MAXINT;
-      info->clip_rect.height = G_MAXINT;
-    }
-}
-
-static void
-gdk_window_compute_parent_pos (GdkWindowImplX11      *window,
-                              GdkWindowParentPos *parent_pos)
-{
-  GdkWindowObject *wrapper;
-  GdkWindowObject *parent;
-  GdkRectangle tmp_clip;
-  
-  int clip_xoffset = 0;
-  int clip_yoffset = 0;
-
-  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (window));
-
-  wrapper =
-    GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_X11 (window)->wrapper);
-  
-  parent_pos->x = 0;
-  parent_pos->y = 0;
-  parent_pos->x11_x = 0;
-  parent_pos->x11_y = 0;
-
-  /* We take a simple approach here and simply consider toplevel
-   * windows not to clip their children on the right/bottom, since the
-   * size of toplevel windows is not directly under our
-   * control. Clipping only really matters when scrolling and
-   * generally we aren't going to be moving the immediate child of a
-   * toplevel beyond the bounds of that toplevel.
-   *
-   * We could go ahead and recompute the clips of toplevel windows and
-   * their descendents when we receive size notification, but it would
-   * probably not be an improvement in most cases.
-   */
-  parent_pos->clip_rect.x = 0;
-  parent_pos->clip_rect.y = 0;
-  parent_pos->clip_rect.width = G_MAXINT;
-  parent_pos->clip_rect.height = G_MAXINT;
-
-  parent = (GdkWindowObject *)wrapper->parent;
-  while (parent && parent->window_type == GDK_WINDOW_CHILD)
-    {
-      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (parent->impl);
-      
-      tmp_clip.x = - clip_xoffset;
-      tmp_clip.y = - clip_yoffset;
-      tmp_clip.width = impl->width;
-      tmp_clip.height = impl->height;
-
-      gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
-
-      translate_pos (parent_pos, parent_pos, parent,
-                     &impl->position_info, FALSE);
-
-      clip_xoffset += parent->x;
-      clip_yoffset += parent->y;
-
-      parent = (GdkWindowObject *)parent->parent;
-    }
-}
-
-static void
-gdk_window_premove (GdkWindow          *window,
-                   GdkWindowParentPos *parent_pos)
-{
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *obj;
-  GdkXPositionInfo new_info;
-  gint d_xoffset, d_yoffset;
-  GdkWindowParentPos this_pos;
-
-  obj = (GdkWindowObject *) window;
-  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-  
-  gdk_window_compute_position (impl, parent_pos, &new_info);
-
-  gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
-
-  translate_pos (&this_pos, parent_pos, obj, &new_info, TRUE);
-
-  unmap_if_needed (window, &new_info);
-
-  d_xoffset = new_info.x_offset - impl->position_info.x_offset;
-  d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-  
-  if (d_xoffset != 0 || d_yoffset != 0)
-    {
-      GdkRectangle new_position;
-
-      if (d_xoffset < 0 || d_yoffset < 0)
-       gdk_window_queue_translation (window, NULL, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-
-      compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
-                                    &new_position);
-
-      move_resize (window, &new_position);
-    }
-
-  g_list_foreach (obj->children, (GFunc) gdk_window_premove, &this_pos);
-}
-
-static void
-gdk_window_postmove (GdkWindow          *window,
-                    GdkWindowParentPos *parent_pos)
-{
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *obj;
-  GdkXPositionInfo new_info;
-  gint d_xoffset, d_yoffset;
-  GdkWindowParentPos this_pos;
-
-  obj = (GdkWindowObject *) window;
-  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-  
-  gdk_window_compute_position (impl, parent_pos, &new_info);
-
-  translate_pos (&this_pos, parent_pos, obj, &new_info, TRUE);
-
-  d_xoffset = new_info.x_offset - impl->position_info.x_offset;
-  d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-  
-  if (d_xoffset != 0 || d_yoffset != 0)
-    {
-      if (d_xoffset > 0 || d_yoffset > 0)
-       gdk_window_queue_translation (window, NULL, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
-       
-      move_resize (window, (GdkRectangle *) &new_info);
-    }
-
-  map_if_needed (window, &new_info);
-
-  reset_backgrounds (window);
-
-  impl->position_info = new_info;
-
-  g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &this_pos);
+    move (window, &new_info);
 }
 
 static Bool
@@ -1050,11 +356,11 @@ gdk_window_queue (GdkWindow          *window,
   g_queue_push_tail (display_x11->translate_queue, item);
 }
 
-static void
-gdk_window_queue_translation (GdkWindow *window,
-                             GdkRegion *area,
-                             gint       dx,
-                             gint       dy)
+void
+_gdk_windowing_window_queue_translation (GdkWindow *window,
+                                        GdkRegion *area,
+                                        gint       dx,
+                                        gint       dy)
 {
   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
   item->type = GDK_WINDOW_QUEUE_TRANSLATE;
@@ -1066,8 +372,8 @@ gdk_window_queue_translation (GdkWindow *window,
 }
 
 gboolean
-_gdk_windowing_window_queue_antiexpose (GdkWindow *window,
-                                       GdkRegion *area)
+_gdk_x11_window_queue_antiexpose (GdkWindow *window,
+                                 GdkRegion *area)
 {
   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
   item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
@@ -1085,7 +391,6 @@ _gdk_window_process_expose (GdkWindow    *window,
 {
   GdkWindowImplX11 *impl;
   GdkRegion *invalidate_region = gdk_region_rectangle (area);
-  GdkRegion *clip_region;
   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
   impl = GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
 
@@ -1134,57 +439,10 @@ _gdk_window_process_expose (GdkWindow    *window,
        }
     }
 
-  clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
-  gdk_region_intersect (invalidate_region, clip_region);
-
   if (!gdk_region_empty (invalidate_region))
-    gdk_window_invalidate_region (window, invalidate_region, FALSE);
+    _gdk_window_invalidate_for_expose (window, invalidate_region);
   
   gdk_region_destroy (invalidate_region);
-  gdk_region_destroy (clip_region);
-}
-
-static void
-gdk_window_clip_changed (GdkWindow *window, GdkRectangle *old_clip, GdkRectangle *new_clip)
-{
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *obj;
-  GdkRegion *old_clip_region;
-  GdkRegion *new_clip_region;
-  
-  if (((GdkWindowObject *)window)->input_only)
-    return;
-
-  obj = (GdkWindowObject *) window;
-  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-  
-  old_clip_region = gdk_region_rectangle (old_clip);
-  new_clip_region = gdk_region_rectangle (new_clip);
-
-  /* We need to update this here because gdk_window_invalidate_region makes
-   * use if it (through gdk_drawable_get_visible_region
-   */
-  impl->position_info.clip_rect = *new_clip;
-  
-  /* Trim invalid region of window to new clip rectangle
-   */
-  if (obj->update_area)
-    gdk_region_intersect (obj->update_area, new_clip_region);
-
-  /* Invalidate newly exposed portion of window
-   */
-  gdk_region_subtract (new_clip_region, old_clip_region);
-  if (!gdk_region_empty (new_clip_region))
-    {
-      _gdk_x11_window_tmp_unset_bg (window, FALSE);;
-      gdk_window_invalidate_region (window, new_clip_region, FALSE);
-    }
-
-  if (obj->parent)
-    _gdk_x11_window_tmp_unset_bg ((GdkWindow *)obj->parent, FALSE);
-  
-  gdk_region_destroy (new_clip_region);
-  gdk_region_destroy (old_clip_region);
 }
 
 #define __GDK_GEOMETRY_X11_C__
index 0d48e13f3ba3b5f3d748af7833fe97c933566a7c..87fe45cc04a45858c91348e8dc37a279cda7ce82 100644 (file)
@@ -251,7 +251,7 @@ gdk_device_get_history  (GdkDevice         *device,
   int tmp_n_events = 0;
   int i;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), FALSE);
 
   if (GDK_WINDOW_DESTROYED (window))
     /* Nothing */ ;
@@ -347,7 +347,7 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask,
   GdkDisplayX11 *display_x11;
 
   g_return_if_fail (window != NULL);
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_WINDOW_IS_X11 (window));
 
   window_private = (GdkWindowObject*) window;
   display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
index 7bede228a18315252ba292c6f3fe084905dcdef4..dd75b63c5c564afd97bff2479fe2980e3389b06c 100644 (file)
@@ -143,17 +143,17 @@ generate_grab_broken_event (GdkWindow *window,
                            gboolean   implicit,
                            GdkWindow *grab_window)
 {
+  g_return_if_fail (window != NULL);
+
   if (!GDK_WINDOW_DESTROYED (window))
     {
       GdkEvent event;
-  
       event.type = GDK_GRAB_BROKEN;
       event.grab_broken.window = window;
       event.grab_broken.send_event = 0;
       event.grab_broken.keyboard = keyboard;
       event.grab_broken.implicit = implicit;
       event.grab_broken.grab_window = grab_window;
-      
       gdk_event_put (&event);
     }
 }
@@ -191,6 +191,7 @@ gdk_pointer_grab (GdkWindow *         window,
 {
   gint return_val;
   GdkCursorPrivate *cursor_private;
+  GdkWindow *native;
   GdkDisplayX11 *display_x11;
   guint xevent_mask;
   Window xwindow;
@@ -202,13 +203,18 @@ gdk_pointer_grab (GdkWindow *       window,
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
-  
-  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+
+  native = _gdk_window_get_impl_window (window);
+
+  if (confine_to)
+    confine_to = _gdk_window_get_impl_window (confine_to);
+
+  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
 
   cursor_private = (GdkCursorPrivate*) cursor;
   
-  xwindow = GDK_WINDOW_XID (window);
-  serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
+  xwindow = GDK_WINDOW_XID (native);
+  serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
   
   if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
     xconfine_to = None;
@@ -230,7 +236,7 @@ gdk_pointer_grab (GdkWindow *         window,
        xevent_mask |= _gdk_event_mask_table[i];
     }
   
-  return_val = _gdk_input_grab_pointer (window,
+  return_val = _gdk_input_grab_pointer (native,
                                        owner_events,
                                        event_mask,
                                        confine_to,
@@ -239,14 +245,14 @@ gdk_pointer_grab (GdkWindow *       window,
   if (return_val == GrabSuccess || 
       G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed))
     {
-      if (!GDK_WINDOW_DESTROYED (window))
+      if (!GDK_WINDOW_DESTROYED (native))
        {
 #ifdef G_ENABLE_DEBUG
          if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
            return_val = GrabSuccess;
          else
 #endif
-           return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (window),
+           return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (native),
                                       xwindow,
                                       owner_events,
                                       xevent_mask,
@@ -261,59 +267,19 @@ gdk_pointer_grab (GdkWindow *       window,
   
   if (return_val == GrabSuccess)
     {
-      if (display_x11->pointer_xgrab_window != NULL &&
-         display_x11->pointer_xgrab_window != (GdkWindowObject *)window)
-       generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-                                   FALSE, display_x11->pointer_xgrab_implicit,
-                                   window);
-
-      display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
-      display_x11->pointer_xgrab_serial = serial;
-      display_x11->pointer_xgrab_owner_events = owner_events;
-      display_x11->pointer_xgrab_time = time;
-      display_x11->pointer_xgrab_implicit = FALSE;
+      _gdk_display_set_has_pointer_grab (GDK_DISPLAY_OBJECT (display_x11),
+                                        window,
+                                        native,
+                                        owner_events,
+                                        event_mask,
+                                        serial,
+                                        time,
+                                        FALSE);
     }
 
   return gdk_x11_convert_grab_status (return_val);
 }
 
-/**
- * gdk_pointer_grab_info_libgtk_only:
- * @display: the #GdkDisplay for which to get the grab information
- * @grab_window: location to store current grab window
- * @owner_events: location to store boolean indicating whether
- *   the @owner_events flag to gdk_pointer_grab() was %TRUE.
- * 
- * Determines information about the current pointer grab.
- * This is not public API and must not be used by applications.
- * 
- * Return value: %TRUE if this application currently has the
- *  pointer grabbed.
- **/
-gboolean
-gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
-                                  GdkWindow **grab_window,
-                                  gboolean   *owner_events)
-{
-  GdkDisplayX11 *display_x11;
-  
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), False);
-
-  display_x11 = GDK_DISPLAY_X11 (display);
-
-  if (display_x11->pointer_xgrab_window)
-    {
-      if (grab_window)
-        *grab_window = (GdkWindow *)display_x11->pointer_xgrab_window;
-      if (owner_events)
-        *owner_events = display_x11->pointer_xgrab_owner_events;
-
-      return TRUE;
-    }
-  else
-    return FALSE;
-}
-
 /*
  *--------------------------------------------------------------
  * gdk_keyboard_grab
@@ -342,23 +308,28 @@ gdk_keyboard_grab (GdkWindow *       window,
   gint return_val;
   unsigned long serial;
   GdkDisplayX11 *display_x11;
+  GdkWindow *native;
+
+  if (1) return 0; /* TODO: fix */
   
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
-  
-  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
 
-  serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
+  native = _gdk_window_get_impl_window (window);
 
-  if (!GDK_WINDOW_DESTROYED (window))
+  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
+
+  serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
+
+  if (!GDK_WINDOW_DESTROYED (native))
     {
 #ifdef G_ENABLE_DEBUG
       if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
        return_val = GrabSuccess;
       else
 #endif
-       return_val = XGrabKeyboard (GDK_WINDOW_XDISPLAY (window),
-                                   GDK_WINDOW_XID (window),
+       return_val = XGrabKeyboard (GDK_WINDOW_XDISPLAY (native),
+                                   GDK_WINDOW_XID (native),
                                    owner_events,
                                    GrabModeAsync, GrabModeAsync,
                                    time);
@@ -378,6 +349,7 @@ gdk_keyboard_grab (GdkWindow *         window,
                                    TRUE, FALSE, window);
       
       display_x11->keyboard_xgrab_window = (GdkWindowObject *)window;
+      display_x11->keyboard_xgrab_native_window = (GdkWindowObject *)native;
       display_x11->keyboard_xgrab_serial = serial;
       display_x11->keyboard_xgrab_owner_events = owner_events;
       display_x11->keyboard_xgrab_time = time;      
@@ -386,6 +358,24 @@ gdk_keyboard_grab (GdkWindow *        window,
   return gdk_x11_convert_grab_status (return_val);
 }
 
+void
+_gdk_windowing_grab_broken (GdkDisplay *display)
+{
+  /* TODO: Move to common code */
+#if 0
+  GdkDisplayX11 *display_x11;
+
+  g_return_if_fail (display != NULL);
+
+  display_x11 = GDK_DISPLAY_X11 (display);
+  generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_grab.window),
+                              FALSE,
+                              display_x11->pointer_grab.implicit,
+                              NULL);
+  display_x11->pointer_grab.window = NULL;
+#endif
+}
+
 /**
  * gdk_keyboard_grab_info_libgtk_only:
  * @display: the display for which to get the grab information
@@ -437,24 +427,20 @@ void
 _gdk_xgrab_check_unmap (GdkWindow *window,
                        gulong     serial)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+  GdkDisplay *display = gdk_drawable_get_display (window);
+  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
   
-  if (display_x11->pointer_xgrab_window && 
-      serial >= display_x11->pointer_xgrab_serial)
+  if (display->pointer_grab.window && 
+      serial >= display->pointer_grab.serial)
     {
       GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
-      GdkWindowObject *tmp = display_x11->pointer_xgrab_window;
+      GdkWindowObject *tmp = GDK_WINDOW_OBJECT (display->pointer_grab.native_window);
 
       while (tmp && tmp != private)
        tmp = tmp->parent;
 
       if (tmp)
-       {         
-         generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-                                     FALSE, display_x11->pointer_xgrab_implicit, 
-                                     NULL);
-         display_x11->pointer_xgrab_window = NULL;  
-       }
+       _gdk_display_unset_has_pointer_grab (display, TRUE, FALSE, GDK_CURRENT_TIME);
     }
 
   if (display_x11->keyboard_xgrab_window &&
@@ -486,17 +472,15 @@ _gdk_xgrab_check_unmap (GdkWindow *window,
 void
 _gdk_xgrab_check_destroy (GdkWindow *window)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+  GdkDisplay *display = gdk_drawable_get_display (window);
+  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
   
-  if ((GdkWindowObject *)window == display_x11->pointer_xgrab_window)
-    {
-      generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-                                 FALSE, display_x11->pointer_xgrab_implicit,
-                                 NULL);
-      display_x11->pointer_xgrab_window = NULL;
-    }
+  if (window == display->pointer_grab.native_window &&
+      display->pointer_grab.window != NULL)
+    _gdk_display_unset_has_pointer_grab (display, TRUE, FALSE, GDK_CURRENT_TIME);
 
-  if ((GdkWindowObject *)window ==  display_x11->keyboard_xgrab_window)
+  if ((GdkWindowObject *)window == display_x11->keyboard_xgrab_native_window &&
+      display_x11->keyboard_xgrab_window != NULL)
     {
       generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
                                  TRUE, FALSE, NULL);
@@ -521,27 +505,31 @@ void
 _gdk_xgrab_check_button_event (GdkWindow *window, 
                               XEvent *xevent)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+  GdkDisplay *display = gdk_drawable_get_display (window);
   
   /* track implicit grabs for button presses */
   switch (xevent->type)
     {
     case ButtonPress:
-      if (!display_x11->pointer_xgrab_window)
+      if (!display->pointer_grab.window)
        {
-         display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
-         display_x11->pointer_xgrab_serial = xevent->xany.serial;
-         display_x11->pointer_xgrab_owner_events = FALSE;
-         display_x11->pointer_xgrab_time = xevent->xbutton.time;
-         display_x11->pointer_xgrab_implicit = TRUE;     
+         _gdk_display_set_has_pointer_grab (display,
+                                            window,
+                                            window,
+                                            FALSE,
+                                            gdk_window_get_events (window),
+                                            xevent->xany.serial,
+                                            xevent->xbutton.time,
+                                            TRUE);
        }
       break;
     case ButtonRelease:
-      if (display_x11->pointer_xgrab_window &&
-         display_x11->pointer_xgrab_implicit &&
+      if (display->pointer_grab.window &&
+         display->pointer_grab.implicit &&
          (xevent->xbutton.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (xevent->xbutton.button - 1))) == 0)
        {
-         display_x11->pointer_xgrab_window = NULL;
+         _gdk_display_unset_has_pointer_grab (display, TRUE, TRUE,
+                                              xevent->xbutton.time);
        }
       break;
     default:
index 7984b5a08962035280e0882ad4403878a8721d06..1fcaf5a9b42ca097eba050ea3503bb6ddb0c5154 100644 (file)
@@ -137,10 +137,10 @@ gdk_pixmap_impl_x11_get_size   (GdkDrawable *drawable,
 }
 
 GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
-               gint         width,
-               gint         height,
-               gint         depth)
+_gdk_pixmap_new (GdkDrawable *drawable,
+                 gint         width,
+                 gint         height,
+                 gint         depth)
 {
   GdkPixmap *pixmap;
   GdkDrawableImplX11 *draw_impl;
@@ -194,10 +194,10 @@ gdk_pixmap_new (GdkDrawable *drawable,
 }
 
 GdkPixmap *
-gdk_bitmap_create_from_data (GdkDrawable *drawable,
-                            const gchar *data,
-                            gint         width,
-                            gint         height)
+_gdk_bitmap_create_from_data (GdkDrawable *drawable,
+                              const gchar *data,
+                              gint         width,
+                              gint         height)
 {
   GdkPixmap *pixmap;
   GdkDrawableImplX11 *draw_impl;
@@ -238,13 +238,13 @@ gdk_bitmap_create_from_data (GdkDrawable *drawable,
 }
 
 GdkPixmap*
-gdk_pixmap_create_from_data (GdkDrawable    *drawable,
-                            const gchar    *data,
-                            gint            width,
-                            gint            height,
-                            gint            depth,
-                            const GdkColor *fg,
-                            const GdkColor *bg)
+_gdk_pixmap_create_from_data (GdkDrawable    *drawable,
+                             const gchar    *data,
+                             gint            width,
+                             gint            height,
+                             gint            depth,
+                             const GdkColor *fg,
+                             const GdkColor *bg)
 {
   GdkPixmap *pixmap;
   GdkDrawableImplX11 *draw_impl;
index f24a0df4c1adec038c04f4cf88e298ac0720823d..ad1dfca7db88889fcb82c92542c4d2d20957780d 100644 (file)
@@ -118,7 +118,6 @@ GdkImage *_gdk_x11_copy_to_image       (GdkDrawable *drawable,
 Pixmap   _gdk_x11_image_get_shm_pixmap (GdkImage    *image);
 
 /* Routines from gdkgeometry-x11.c */
-void _gdk_window_init_position     (GdkWindow     *window);
 void _gdk_window_move_resize_child (GdkWindow     *window,
                                     gint           x,
                                     gint           y,
@@ -128,13 +127,9 @@ void _gdk_window_process_expose    (GdkWindow     *window,
                                     gulong         serial,
                                     GdkRectangle  *area);
 
-void _gdk_x11_window_scroll        (GdkWindow       *window,
-                                    gint             dx,
-                                    gint             dy);
-void _gdk_x11_window_move_region   (GdkWindow       *window,
-                                    const GdkRegion *region,
-                                    gint             dx,
-                                    gint             dy);
+gboolean _gdk_x11_window_queue_antiexpose (GdkWindow *window,
+                                          GdkRegion *area);
+
 
 void     _gdk_selection_window_destroyed   (GdkWindow            *window);
 gboolean _gdk_selection_filter_clear_event (XSelectionClearEvent *event);
@@ -216,5 +211,6 @@ extern gboolean          _gdk_synchronize;
 #define GDK_WINDOW_DISPLAY(win)       (GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (win))->display)
 #define GDK_WINDOW_XROOTWIN(win)      (GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (win))->xroot_window)
 #define GDK_GC_DISPLAY(gc)            (GDK_SCREEN_DISPLAY (GDK_GC_X11(gc)->screen))
+#define GDK_WINDOW_IS_X11(win)        (GDK_IS_WINDOW_IMPL_X11 (((GdkWindowObject *)win)->impl))
 
 #endif /* __GDK_PRIVATE_X11_H__ */
index 36b8e9fcc41d871c18cc8b477d228829c6731258..0310a75222244943e345ddaa5139ad3076667bbd 100644 (file)
@@ -541,7 +541,7 @@ gdk_property_get (GdkWindow   *window,
   Atom xtype;
   int res;
 
-  g_return_val_if_fail (!window || GDK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (!window || GDK_WINDOW_IS_X11 (window), FALSE);
 
   if (!window)
     {
@@ -550,6 +550,8 @@ gdk_property_get (GdkWindow   *window,
       
       GDK_NOTE (MULTIHEAD, g_message ("gdk_property_get(): window is NULL\n"));
     }
+  else if (!GDK_WINDOW_IS_X11 (window))
+    return FALSE;
 
   if (GDK_WINDOW_DESTROYED (window))
     return FALSE;
@@ -675,7 +677,7 @@ gdk_property_change (GdkWindow    *window,
   Atom xproperty;
   Atom xtype;
 
-  g_return_if_fail (!window || GDK_IS_WINDOW (window));
+  g_return_if_fail (!window || GDK_WINDOW_IS_X11 (window));
 
   if (!window)
     {
@@ -686,7 +688,8 @@ gdk_property_change (GdkWindow    *window,
       
       GDK_NOTE (MULTIHEAD, g_message ("gdk_property_change(): window is NULL\n"));
     }
-
+  else if (!GDK_WINDOW_IS_X11 (window))
+    return;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -726,7 +729,7 @@ void
 gdk_property_delete (GdkWindow *window,
                     GdkAtom    property)
 {
-  g_return_if_fail (!window || GDK_IS_WINDOW (window));
+  g_return_if_fail (!window || GDK_WINDOW_IS_X11 (window));
 
   if (!window)
     {
@@ -736,6 +739,8 @@ gdk_property_delete (GdkWindow *window,
       GDK_NOTE (MULTIHEAD, 
                g_message ("gdk_property_delete(): window is NULL\n"));
     }
+  else if (!GDK_WINDOW_IS_X11 (window))
+    return;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
index fd482e2fb301d79a8b0881493b2f007de3e457b8..d9ef881a2e2ccaee14640420c796090a2cb22a0b 100644 (file)
@@ -141,7 +141,7 @@ gdk_selection_owner_set_for_display (GdkDisplay *display,
 
   if (owner) 
     {
-      if (GDK_WINDOW_DESTROYED (owner))
+      if (GDK_WINDOW_DESTROYED (owner) || !GDK_WINDOW_IS_X11 (owner))
        return FALSE;
       
       xdisplay = GDK_WINDOW_XDISPLAY (owner);
@@ -231,7 +231,7 @@ gdk_selection_convert (GdkWindow *requestor,
 
   g_return_if_fail (selection != GDK_NONE);
   
-  if (GDK_WINDOW_DESTROYED (requestor))
+  if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
     return;
 
   display = GDK_WINDOW_DISPLAY (requestor);
@@ -279,10 +279,11 @@ gdk_selection_property_get (GdkWindow  *requestor,
 
   g_return_val_if_fail (requestor != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
+  g_return_val_if_fail (GDK_WINDOW_IS_X11 (requestor), 0);
   
   display = GDK_WINDOW_DISPLAY (requestor);
 
-  if (GDK_WINDOW_DESTROYED (requestor))
+  if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
     goto err;
 
   t = NULL;
index a6d88b9ffc8691097dd2e9075a2081dfeb7b7764..b5a3a3aa84fbc1a30bdbeb31420b868bcd01a9b7 100644 (file)
@@ -112,16 +112,13 @@ static void     move_to_current_desktop           (GdkWindow *window);
 static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
 static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
                                                      GdkColormap *cmap);
-static void         gdk_window_impl_x11_get_size    (GdkDrawable *drawable,
-                                                    gint *width,
-                                                    gint *height);
-static GdkRegion*  gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable);
 static void        gdk_window_impl_x11_finalize   (GObject            *object);
 static void        gdk_window_impl_iface_init     (GdkWindowImplIface *iface);
 
-#define WINDOW_IS_TOPLEVEL(window)                \
-  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
-   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+#define WINDOW_IS_TOPLEVEL(window)                  \
+  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
 
 /* Return whether time1 is considered later than time2 as far as xserver
  * time is concerned.  Accounts for wraparound.
@@ -146,8 +143,6 @@ _gdk_window_impl_get_type (void)
 static void
 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
 {  
-  impl->width = 1;
-  impl->height = 1;
   impl->toplevel_window_type = -1;
 }
 
@@ -181,11 +176,6 @@ gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
 
   drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
   drawable_class->get_colormap = gdk_window_impl_x11_get_colormap;
-  drawable_class->get_size = gdk_window_impl_x11_get_size;
-
-  /* Visible and clip regions are the same */
-  drawable_class->get_clip_region = gdk_window_impl_x11_get_visible_region;
-  drawable_class->get_visible_region = gdk_window_impl_x11_get_visible_region;
 }
 
 static void
@@ -237,7 +227,7 @@ tmp_unset_bg (GdkWindow *window)
   if (!(obj->event_mask & GDK_EXPOSURE_MASK))
     return;
     
-  impl->position_info.no_bg = TRUE;
+  impl->no_bg = TRUE;
 
   if (obj->bg_pixmap != GDK_NO_BG)
     XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
@@ -256,7 +246,7 @@ tmp_reset_bg (GdkWindow *window)
   if (!(obj->event_mask & GDK_EXPOSURE_MASK))
     return;
     
-  impl->position_info.no_bg = FALSE;
+  impl->no_bg = FALSE;
 
   if (obj->bg_pixmap == GDK_NO_BG)
     return;
@@ -300,7 +290,9 @@ _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
 
   if (private->input_only || private->destroyed ||
       (private->window_type != GDK_WINDOW_ROOT &&
-       !GDK_WINDOW_IS_MAPPED (window)))
+       !GDK_WINDOW_IS_MAPPED (window)) ||
+      !_gdk_window_has_impl (window) ||
+      !GDK_WINDOW_IS_X11 (window))
     {
       return;
     }
@@ -332,7 +324,9 @@ _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
 
   if (private->input_only || private->destroyed ||
       (private->window_type != GDK_WINDOW_ROOT &&
-       !GDK_WINDOW_IS_MAPPED (window)))
+       !GDK_WINDOW_IS_MAPPED (window)) ||
+      !_gdk_window_has_impl (window) ||
+      !GDK_WINDOW_IS_X11 (window))
     {
       return;
     }
@@ -409,35 +403,6 @@ gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
 }
 
 
-static void
-gdk_window_impl_x11_get_size (GdkDrawable *drawable,
-                              gint        *width,
-                              gint        *height)
-{
-  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
-
-  if (width)
-    *width = GDK_WINDOW_IMPL_X11 (drawable)->width;
-  if (height)
-    *height = GDK_WINDOW_IMPL_X11 (drawable)->height;
-}
-
-static GdkRegion*
-gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable)
-{
-  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (drawable);
-  GdkRectangle result_rect;
-
-  result_rect.x = 0;
-  result_rect.y = 0;
-  result_rect.width = impl->width;
-  result_rect.height = impl->height;
-
-  gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
-
-  return gdk_region_rectangle (&result_rect);
-}
-
 void
 _gdk_windowing_window_init (GdkScreen * screen)
 {
@@ -469,12 +434,14 @@ _gdk_windowing_window_init (GdkScreen * screen)
   
   private->window_type = GDK_WINDOW_ROOT;
   private->depth = DefaultDepthOfScreen (screen_x11->xscreen);
-  
-  impl->width = WidthOfScreen (screen_x11->xscreen);
-  impl->height = HeightOfScreen (screen_x11->xscreen);
-  
-  _gdk_window_init_position (GDK_WINDOW (private));
 
+  private->x = 0;
+  private->y = 0;
+  private->abs_x = 0;
+  private->abs_y = 0;
+  private->width = WidthOfScreen (screen_x11->xscreen);
+  private->height = HeightOfScreen (screen_x11->xscreen);
+  
   _gdk_xid_table_insert (screen_x11->display,
                         &screen_x11->xroot_window,
                         screen_x11->root_window);
@@ -589,7 +556,6 @@ setup_toplevel_window (GdkWindow *window,
 {
   GdkWindowObject *obj = (GdkWindowObject *)window;
   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
-  GdkWindowImplX11 *impl = (GdkWindowImplX11 *)obj->impl;
   Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
   XID xid = GDK_WINDOW_XID (window);
   XID xparent = GDK_WINDOW_XID (parent);
@@ -619,8 +585,8 @@ setup_toplevel_window (GdkWindow *window,
    * correct value???
    */
   size_hints.flags = PSize;
-  size_hints.width = impl->width;
-  size_hints.height = impl->height;
+  size_hints.width = obj->width;
+  size_hints.height = obj->height;
   
   XSetWMNormalHints (xdisplay, xid, &size_hints);
   
@@ -656,19 +622,19 @@ setup_toplevel_window (GdkWindow *window,
   ensure_sync_counter (window);
 }
 
-GdkWindow *
-_gdk_window_new (GdkWindow     *parent,
-                GdkWindowAttr *attributes,
-                gint           attributes_mask)
+void
+_gdk_window_impl_new (GdkWindow     *window,
+                     GdkScreen     *screen,
+                     GdkVisual     *visual,
+                     GdkEventMask   event_mask,
+                     GdkWindowAttr *attributes,
+                     gint           attributes_mask)
 {
-  GdkWindow *window;
   GdkWindowObject *private;
   GdkWindowImplX11 *impl;
   GdkDrawableImplX11 *draw_impl;
   GdkScreenX11 *screen_x11;
-  GdkScreen *screen;
   
-  GdkVisual *visual;
   Window xparent;
   Visual *xvisual;
   Display *xdisplay;
@@ -677,117 +643,35 @@ _gdk_window_new (GdkWindow     *parent,
   XSetWindowAttributes xattributes;
   long xattributes_mask;
   XClassHint *class_hint;
-  int x, y, depth;
+  int depth;
   
   unsigned int class;
   const char *title;
   int i;
   
-  g_return_val_if_fail (attributes != NULL, NULL);
+  private = (GdkWindowObject *) window;
   
-  if (!parent)
-    {
-      GDK_NOTE (MULTIHEAD,
-               g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
-      
-      screen = gdk_screen_get_default ();
-      parent = gdk_screen_get_root_window (screen);
-    }
-  else
-    screen = gdk_drawable_get_screen (parent);
-
   screen_x11 = GDK_SCREEN_X11 (screen);
-
-  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
-  
-  if (GDK_WINDOW_DESTROYED (parent))
-    return NULL;
+  xparent = GDK_WINDOW_XID (private->parent);
   
-  xparent = GDK_WINDOW_XID (parent);
-  
-  window = g_object_new (GDK_TYPE_WINDOW, NULL);
-
-  private = (GdkWindowObject *) window;
-  private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
-
-  impl = GDK_WINDOW_IMPL_X11 (private->impl);
-  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
+  impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+  private->impl = (GdkDrawable *)impl;
+  draw_impl = GDK_DRAWABLE_IMPL_X11 (impl);
   draw_impl->wrapper = GDK_DRAWABLE (window);
   
   draw_impl->screen = screen;
   xdisplay = screen_x11->xdisplay;
 
-  /* Windows with a foreign parent are treated as if they are children
-   * of the root window, except for actual creation.
-   */
-  if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
-    parent = gdk_screen_get_root_window (screen);
-  
-  private->parent = (GdkWindowObject *)parent;
-
-  private->accept_focus = TRUE;
-  private->focus_on_map = TRUE;
-
   xattributes_mask = 0;
-  
-  if (attributes_mask & GDK_WA_X)
-    x = attributes->x;
-  else
-    x = 0;
-  
-  if (attributes_mask & GDK_WA_Y)
-    y = attributes->y;
-  else
-    y = 0;
-  
-  private->x = x;
-  private->y = y;
-  impl->width = (attributes->width > 1) ? (attributes->width) : (1);
-  impl->height = (attributes->height > 1) ? (attributes->height) : (1);
-
-  if (attributes->wclass == GDK_INPUT_ONLY)
-    {
-      /* Backwards compatiblity - we've always ignored
-       * attributes->window_type for input-only windows
-       * before
-       */
-      if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
-       private->window_type = GDK_WINDOW_TEMP;
-      else
-       private->window_type = GDK_WINDOW_CHILD;
-    }
-  else
-    private->window_type = attributes->window_type;
-
-  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows 
-   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
-   */
-  if (attributes->wclass == GDK_INPUT_ONLY &&
-      GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT &&
-      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
-    {
-      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
-      attributes->wclass = GDK_INPUT_OUTPUT;
-    }
 
-  _gdk_window_init_position (GDK_WINDOW (private));
-  if (impl->position_info.big)
-    private->guffaw_gravity = TRUE;
-  
-  if (attributes_mask & GDK_WA_VISUAL)
-    visual = attributes->visual;
-  else
-    visual = gdk_screen_get_system_visual (screen);
   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
   
   xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
   for (i = 0; i < _gdk_nenvent_masks; i++)
     {
-      if (attributes->event_mask & (1 << (i + 1)))
+      if (event_mask & (1 << (i + 1)))
        xattributes.event_mask |= _gdk_event_mask_table[i];
     }
-  private->event_mask = attributes->event_mask;
-  
   if (xattributes.event_mask)
     xattributes_mask |= CWEventMask;
   
@@ -814,31 +698,22 @@ _gdk_window_new (GdkWindow     *parent,
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_DIALOG:
     case GDK_WINDOW_TEMP:
-      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+      if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
        {
-         g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
-                    "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+         /* The common code warns for this case */
          xparent = GDK_SCREEN_XROOTWIN (screen);
        }
-    case GDK_WINDOW_CHILD:
-      break;
-    default:
-      g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
-      return NULL;
     }
          
-  if (attributes->wclass == GDK_INPUT_OUTPUT)
+  if (!private->input_only)
     {
       class = InputOutput;
       depth = visual->depth;
 
-      private->input_only = FALSE;
-      private->depth = depth;
-      
-      if (attributes_mask & GDK_WA_COLORMAP)
+      if (private->colormap)
         {
-          draw_impl->colormap = attributes->colormap;
-          g_object_ref (attributes->colormap);
+          draw_impl->colormap = private->colormap;
+          g_object_ref (private->colormap);
         }
       else
        {
@@ -853,12 +728,8 @@ _gdk_window_new (GdkWindow     *parent,
             }
        }
       
-      private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num);
-      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
       xattributes.background_pixel = private->bg_color.pixel;
 
-      private->bg_pixmap = NULL;
-      
       xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
       xattributes_mask |= CWBorderPixel | CWBackPixel;
 
@@ -885,29 +756,25 @@ _gdk_window_new (GdkWindow     *parent,
   else
     {
       depth = 0;
-      private->depth = 0;
       class = InputOnly;
-      private->input_only = TRUE;
       draw_impl->colormap = gdk_screen_get_system_colormap (screen);
       g_object_ref (draw_impl->colormap);
     }
 
   xid = draw_impl->xid = XCreateWindow (xdisplay, xparent,
-                                       impl->position_info.x, impl->position_info.y,
-                                       impl->position_info.width, impl->position_info.height,
+                                       private->x + private->parent->abs_x,
+                                       private->y + private->parent->abs_y,
+                                       private->width, private->height,
                                        0, depth, class, xvisual,
                                        xattributes_mask, &xattributes);
 
   g_object_ref (window);
   _gdk_xid_table_insert (screen_x11->display, &draw_impl->xid, window);
-  
+
   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
                                  (attributes->cursor) :
                                  NULL));
   
-  if (private->parent)
-    private->parent->children = g_list_prepend (private->parent->children, window);
-  
   switch (GDK_WINDOW_TYPE (private))
     {
     case GDK_WINDOW_DIALOG:
@@ -929,11 +796,11 @@ _gdk_window_new (GdkWindow     *parent,
          XFree (class_hint);
        }
   
-      setup_toplevel_window (window, parent);
+      setup_toplevel_window (window, (GdkWindow *)private->parent);
       break;
 
     case GDK_WINDOW_CHILD:
-      if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
+      if (!private->input_only &&
          (draw_impl->colormap != gdk_screen_get_system_colormap (screen)) &&
          (draw_impl->colormap != gdk_drawable_get_colormap (gdk_window_get_toplevel (window))))
        {
@@ -948,8 +815,6 @@ _gdk_window_new (GdkWindow     *parent,
 
   if (attributes_mask & GDK_WA_TYPE_HINT)
     gdk_window_set_type_hint (window, attributes->type_hint);
-
-  return window;
 }
 
 static GdkEventMask
@@ -1044,8 +909,8 @@ gdk_window_foreign_new_for_display (GdkDisplay     *display,
 
   private->x = attrs.x;
   private->y = attrs.y;
-  impl->width = attrs.width;
-  impl->height = attrs.height;
+  private->width = attrs.width;
+  private->height = attrs.height;
   private->window_type = GDK_WINDOW_FOREIGN;
   private->destroyed = FALSE;
 
@@ -1058,8 +923,6 @@ gdk_window_foreign_new_for_display (GdkDisplay     *display,
 
   private->depth = attrs.depth;
   
-  _gdk_window_init_position (GDK_WINDOW (private));
-
   g_object_ref (window);
   _gdk_xid_table_insert (display, &GDK_WINDOW_XID (window), window);
   return window;
@@ -1215,8 +1078,6 @@ gdk_window_destroy_notify (GdkWindow *window)
 {
   GdkWindowImplX11 *window_impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
   window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
 
   if (!GDK_WINDOW_DESTROYED (window))
@@ -1433,6 +1294,7 @@ gdk_window_x11_show (GdkWindow *window,
       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
       Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
       Window xwindow = GDK_WINDOW_XID (window);
+      gboolean unset_bg;
       
       if (raise)
         XRaiseWindow (xdisplay, xwindow);
@@ -1460,23 +1322,20 @@ gdk_window_x11_show (GdkWindow *window,
            gdk_x11_window_set_user_time (window, display_x11->user_time);
        }
 
-      if (impl->position_info.mapped)
+      unset_bg = !private->input_only &&
+       (private->window_type == GDK_WINDOW_CHILD ||
+        impl->override_redirect) &&
+       gdk_window_is_viewable (window);
+      
+      if (unset_bg)
+       _gdk_x11_window_tmp_unset_bg (window, TRUE);
+      
+      XMapWindow (xdisplay, xwindow);
+      
+      if (unset_bg)
        {
-         gboolean unset_bg = !private->input_only &&
-           (private->window_type == GDK_WINDOW_CHILD ||
-            impl->override_redirect) &&
-           gdk_window_is_viewable (window);
-
-         if (unset_bg)
-           _gdk_x11_window_tmp_unset_bg (window, TRUE);
-         
-         XMapWindow (xdisplay, xwindow);
-
-         if (unset_bg)
-           {
-             _gdk_x11_window_tmp_reset_bg (window, TRUE);
-             gdk_window_invalidate_rect (window, NULL, TRUE);
-           }
+         _gdk_x11_window_tmp_reset_bg (window, TRUE);
+         gdk_window_invalidate_rect (window, NULL, TRUE);
        }
     }
 }
@@ -1615,7 +1474,7 @@ window_x11_move (GdkWindow *window,
     {
       _gdk_window_move_resize_child (window,
                                      x, y,
-                                     impl->width, impl->height);
+                                     private->width, private->height);
     }
   else
     {
@@ -1649,7 +1508,6 @@ window_x11_resize (GdkWindow *window,
       _gdk_window_move_resize_child (window,
                                      private->x, private->y,
                                      width, height);
-      _gdk_x11_drawable_update_size (private->impl);
     }
   else
     {
@@ -1661,13 +1519,13 @@ window_x11_resize (GdkWindow *window,
 
       if (impl->override_redirect)
         {
-          impl->width = width;
-          impl->height = height;
+          private->width = width;
+          private->height = height;
           _gdk_x11_drawable_update_size (private->impl);
         }
       else
         {
-          if (width != impl->width || height != impl->height)
+          if (width != private->width || height != private->height)
             private->resize_count += 1;
         }
     }
@@ -1708,14 +1566,14 @@ window_x11_move_resize (GdkWindow *window,
           private->x = x;
           private->y = y;
 
-          impl->width = width;
-          impl->height = height;
+          private->width = width;
+          private->height = height;
 
           _gdk_x11_drawable_update_size (private->impl);
         }
       else
         {
-          if (width != impl->width || height != impl->height)
+          if (width != private->width || height != private->height)
             private->resize_count += 1;
         }
     }
@@ -1750,10 +1608,6 @@ gdk_window_x11_reparent (GdkWindow *window,
   GdkWindowObject *parent_private;
   GdkWindowObject *old_parent_private;
   GdkWindowImplX11 *impl;
-  gboolean was_toplevel;
-
-  if (!new_parent)
-    new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
 
   window_private = (GdkWindowObject*) window;
   old_parent_private = (GdkWindowObject*)window_private->parent;
@@ -1763,14 +1617,8 @@ gdk_window_x11_reparent (GdkWindow *window,
   XReparentWindow (GDK_WINDOW_XDISPLAY (window),
                   GDK_WINDOW_XID (window),
                   GDK_WINDOW_XID (new_parent),
-                  x, y);
+                  window_private->abs_x + x, window_private->abs_y + y);
 
-  window_private->x = x;
-  window_private->y = y;
-
-  /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
-   * the root window
-   */
   if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
     new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
 
@@ -1782,54 +1630,44 @@ gdk_window_x11_reparent (GdkWindow *window,
     {
     case GDK_WINDOW_ROOT:
     case GDK_WINDOW_FOREIGN:
-      was_toplevel = WINDOW_IS_TOPLEVEL (window);
-
-      if (impl->toplevel_window_type != -1)
-       GDK_WINDOW_TYPE (window) = impl->toplevel_window_type;
-      else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
-       GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+      /* Reparenting to toplevel */
+      
+      if (!WINDOW_IS_TOPLEVEL (window) &&
+         GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
+       {
+         /* This is also done in common code at a later stage, but we
+            need it in setup_toplevel, so do it here too */
+         if (window_private->toplevel_window_type != -1)
+           GDK_WINDOW_TYPE (window) = window_private->toplevel_window_type;
+         else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+           GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+         
+         /* Wasn't a toplevel, set up */
+         setup_toplevel_window (window, new_parent);
+       }
 
-      if (WINDOW_IS_TOPLEVEL (window) && !was_toplevel)
-       setup_toplevel_window (window, new_parent);
       break;
+      
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_CHILD:
     case GDK_WINDOW_DIALOG:
     case GDK_WINDOW_TEMP:
-      if (WINDOW_IS_TOPLEVEL (window))
+      if (WINDOW_IS_TOPLEVEL (window) &&
+         impl->toplevel)
        {
-         /* Save the original window type so we can restore it if the
-          * window is reparented back to be a toplevel
-          */
-         impl->toplevel_window_type = GDK_WINDOW_TYPE (window);
-         GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
-         if (impl->toplevel)
+         if (impl->toplevel->focus_window)
            {
-             if (impl->toplevel->focus_window)
-               {
-                 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
-                 _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
-               }
-
-             gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
-                                             impl->toplevel);
-             g_free (impl->toplevel);
-             impl->toplevel = NULL;
+             XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
+             _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
            }
+         
+         gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
+                                         impl->toplevel);
+         g_free (impl->toplevel);
+         impl->toplevel = NULL;
        }
     }
 
-  if (old_parent_private)
-    old_parent_private->children = g_list_remove (old_parent_private->children, window);
-
-  if ((old_parent_private &&
-       (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
-      (!old_parent_private && parent_private->guffaw_gravity))
-    gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
-
-  parent_private->children = g_list_prepend (parent_private->children, window);
-  _gdk_window_init_position (GDK_WINDOW (window_private));
-
   return FALSE;
 }
 
@@ -1959,10 +1797,11 @@ gdk_window_focus (GdkWindow *window,
                   guint32    timestamp)
 {
   GdkDisplay *display;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
+  
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = GDK_WINDOW_DISPLAY (window);
@@ -2032,9 +1871,8 @@ gdk_window_set_hints (GdkWindow *window,
 {
   XSizeHints size_hints;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   size_hints.flags = 0;
@@ -2087,9 +1925,8 @@ gdk_window_set_type_hint (GdkWindow        *window,
   GdkDisplay *display;
   Atom atom;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -2172,7 +2009,8 @@ gdk_window_get_type_hint (GdkWindow *window)
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return GDK_WINDOW_TYPE_HINT_NORMAL;
 
   type = GDK_WINDOW_TYPE_HINT_NORMAL;
@@ -2273,9 +2111,8 @@ gdk_window_set_modal_hint (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   private = (GdkWindowObject*) window;
@@ -2308,10 +2145,10 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -2345,10 +2182,10 @@ gdk_window_set_skip_pager_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
     
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -2376,10 +2213,10 @@ gdk_window_set_urgency_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
     
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -2424,9 +2261,8 @@ gdk_window_set_geometry_hints (GdkWindow         *window,
 {
   XSizeHints size_hints;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   size_hints.flags = 0;
@@ -2533,7 +2369,8 @@ gdk_window_get_geometry_hints (GdkWindow      *window,
 
   *geom_mask = 0;
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   size_hints = XAllocSizeHints ();
@@ -2688,10 +2525,10 @@ gdk_window_set_title (GdkWindow   *window,
   Display *xdisplay;
   Window xwindow;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (title != NULL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   display = gdk_drawable_get_display (window);
@@ -2738,11 +2575,10 @@ gdk_window_set_role (GdkWindow   *window,
 {
   GdkDisplay *display;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   display = gdk_drawable_get_display (window);
 
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      WINDOW_IS_TOPLEVEL (window))
     {
       if (role)
        XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
@@ -2767,7 +2603,7 @@ gdk_window_set_role (GdkWindow   *window,
  **/
 void          
 gdk_window_set_startup_id (GdkWindow   *window,
-                    const gchar *startup_id)
+                          const gchar *startup_id)
 {
   GdkDisplay *display;
   
@@ -2775,7 +2611,8 @@ gdk_window_set_startup_id (GdkWindow   *window,
 
   display = gdk_drawable_get_display (window);
 
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      WINDOW_IS_TOPLEVEL (window))
     {
       if (startup_id)
        XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
@@ -2806,9 +2643,8 @@ void
 gdk_window_set_transient_for (GdkWindow *window, 
                              GdkWindow *parent)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent))
+  if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
+      WINDOW_IS_TOPLEVEL (window))
     XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), 
                          GDK_WINDOW_XID (window),
                          GDK_WINDOW_XID (parent));
@@ -2818,62 +2654,22 @@ static void
 gdk_window_x11_set_background (GdkWindow      *window,
                                const GdkColor *color)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkColormap *colormap = gdk_drawable_get_colormap (window);
-  
-  if (!GDK_WINDOW_DESTROYED (window))
-    XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
-                         GDK_WINDOW_XID (window), color->pixel);
-
-  private->bg_color = *color;
-  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
-
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
-  
-  private->bg_pixmap = NULL;
+  XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
+                       GDK_WINDOW_XID (window), color->pixel);
 }
 
 static void
 gdk_window_x11_set_back_pixmap (GdkWindow *window,
-                                GdkPixmap *pixmap,
-                                gboolean   parent_relative)
+                                GdkPixmap *pixmap)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
   Pixmap xpixmap;
   
-  if (pixmap && !gdk_drawable_get_colormap (pixmap))
-    {
-      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
-      return;
-    }
-  
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
-
-  if (parent_relative)
-    {
-      xpixmap = ParentRelative;
-      private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
-    }
+  if (pixmap == GDK_PARENT_RELATIVE_BG)
+    xpixmap = ParentRelative;
+  else if (pixmap == GDK_NO_BG)
+    xpixmap = None;
   else
-    {
-      if (pixmap)
-       {
-         g_object_ref (pixmap);
-         private->bg_pixmap = pixmap;
-         xpixmap = GDK_PIXMAP_XID (pixmap);
-       }
-      else
-       {
-         xpixmap = None;
-         private->bg_pixmap = GDK_NO_BG;
-       }
-    }
+    xpixmap = GDK_PIXMAP_XID (pixmap);
   
   if (!GDK_WINDOW_DESTROYED (window))
     XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
@@ -3026,9 +2822,8 @@ gdk_window_get_deskrelative_origin (GdkWindow *window,
   gulong number_return, bytes_after_return;
   guchar *data_return;
   
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-  
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      WINDOW_IS_TOPLEVEL (window))
     {
       atom = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
                                                    "ENLIGHTENMENT_DESKTOP");
@@ -3092,8 +2887,9 @@ gdk_window_get_root_origin (GdkWindow *window,
 {
   GdkRectangle rect;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return;
+  
   gdk_window_get_frame_extents (window, &rect);
 
   if (x)
@@ -3138,7 +2934,6 @@ gdk_window_get_frame_extents (GdkWindow    *window,
   gint wx, wy;
   gboolean got_frame_extents = FALSE;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (rect != NULL);
   
   private = (GdkWindowObject*) window;
@@ -3148,7 +2943,8 @@ gdk_window_get_frame_extents (GdkWindow    *window,
   rect->width = 1;
   rect->height = 1;
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   while (private->parent && ((GdkWindowObject*) private->parent)->parent)
@@ -3343,12 +3139,9 @@ _gdk_windowing_window_get_pointer (GdkDisplay      *display,
   int winx = 0;
   int winy = 0;
   unsigned int xmask = 0;
-  gint xoffset, yoffset;
 
   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
   
-  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
   return_val = NULL;
   if (!GDK_WINDOW_DESTROYED (window)) 
     {
@@ -3374,8 +3167,8 @@ _gdk_windowing_window_get_pointer (GdkDisplay      *display,
        }
     }
   
-  *x = winx + xoffset;
-  *y = winy + yoffset;
+  *x = winx;
+  *y = winy;
   *mask = xmask;
   
   return return_val;
@@ -3562,8 +3355,8 @@ gdk_window_x11_set_events (GdkWindow    *window,
   
   if (!GDK_WINDOW_DESTROYED (window))
     {
-      GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
       xevent_mask = StructureNotifyMask | PropertyChangeMask;
+
       for (i = 0; i < _gdk_nenvent_masks; i++)
        {
          if (event_mask & (1 << (i + 1)))
@@ -3621,8 +3414,6 @@ gdk_window_add_colormap_windows (GdkWindow *window)
     XFree (old_windows);
 }
 
-#define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
-
 /*
  * This needs the X11 shape extension.
  * If not available, shaped windows will look
@@ -3637,20 +3428,11 @@ do_shape_combine_mask (GdkWindow *window,
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   Pixmap pixmap;
-  gint xoffset, yoffset;
   
 #ifdef HAVE_SHAPE_EXT
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
-  if (xoffset != 0 || yoffset != 0)
-    {
-      WARN_SHAPE_TOO_BIG ();
-      return;
-    }
-  
   if (shape == ShapeBounding
       ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
       : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
@@ -3735,20 +3517,11 @@ do_shape_combine_region (GdkWindow       *window,
                         gint             shape)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
-  gint xoffset, yoffset;
   
 #ifdef HAVE_SHAPE_EXT
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
-  if (xoffset != 0 || yoffset != 0)
-    {
-      WARN_SHAPE_TOO_BIG ();
-      return;
-    }
-  
   if (shape_region == NULL)
     {
       /* Use NULL mask to unset the shape */
@@ -3850,9 +3623,8 @@ gdk_window_set_override_redirect (GdkWindow *window,
 {
   XSetWindowAttributes attr;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      WINDOW_IS_TOPLEVEL (window))
     {
       GdkWindowObject *private = (GdkWindowObject *)window;
       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
@@ -3886,8 +3658,6 @@ gdk_window_set_accept_focus (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   private = (GdkWindowObject *)window;  
   
   accept_focus = accept_focus != FALSE;
@@ -3896,7 +3666,8 @@ gdk_window_set_accept_focus (GdkWindow *window,
     {
       private->accept_focus = accept_focus;
 
-      if (!GDK_WINDOW_DESTROYED (window))
+      if (!GDK_WINDOW_DESTROYED (window) &&
+         WINDOW_IS_TOPLEVEL (window))
        update_wm_hints (window, FALSE);
     }
 }
@@ -3923,8 +3694,6 @@ gdk_window_set_focus_on_map (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   private = (GdkWindowObject *)window;  
   
   focus_on_map = focus_on_map != FALSE;
@@ -3932,8 +3701,10 @@ gdk_window_set_focus_on_map (GdkWindow *window,
   if (private->focus_on_map != focus_on_map)
     {
       private->focus_on_map = focus_on_map;
-
-      if ((!GDK_WINDOW_DESTROYED (window)) && (!private->focus_on_map))
+      
+      if ((!GDK_WINDOW_DESTROYED (window)) &&
+         (!private->focus_on_map) &&
+         WINDOW_IS_TOPLEVEL (window))
        gdk_x11_window_set_user_time (window, 0);
     }
 }
@@ -3968,9 +3739,8 @@ gdk_x11_window_set_user_time (GdkWindow *window,
   glong timestamp_long = (glong)timestamp;
   Window xid;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -4038,9 +3808,8 @@ gdk_window_set_icon_list (GdkWindow *window,
   GdkDisplay *display;
   gint n;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -4150,10 +3919,10 @@ gdk_window_set_icon (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -4210,9 +3979,8 @@ gdk_window_set_icon_name (GdkWindow   *window,
 {
   GdkDisplay *display;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -4245,9 +4013,8 @@ gdk_window_set_icon_name (GdkWindow   *window,
 void
 gdk_window_iconify (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4279,9 +4046,8 @@ gdk_window_iconify (GdkWindow *window)
 void
 gdk_window_deiconify (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4315,9 +4081,8 @@ gdk_window_deiconify (GdkWindow *window)
 void
 gdk_window_stick (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4372,9 +4137,8 @@ gdk_window_stick (GdkWindow *window)
 void
 gdk_window_unstick (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4416,9 +4180,8 @@ gdk_window_unstick (GdkWindow *window)
 void
 gdk_window_maximize (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4451,9 +4214,8 @@ gdk_window_maximize (GdkWindow *window)
 void
 gdk_window_unmaximize (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4489,9 +4251,8 @@ gdk_window_unmaximize (GdkWindow *window)
 void
 gdk_window_fullscreen (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4525,9 +4286,8 @@ gdk_window_fullscreen (GdkWindow *window)
 void
 gdk_window_unfullscreen (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4564,7 +4324,8 @@ gdk_window_set_keep_above (GdkWindow *window,
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4605,7 +4366,8 @@ gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4639,10 +4401,10 @@ gdk_window_get_group (GdkWindow *window)
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
   g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return NULL;
   
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -4672,11 +4434,12 @@ gdk_window_set_group (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
-  g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
+  g_return_if_fail (leader == NULL);
 
-  if (GDK_WINDOW_DESTROYED (window) || (leader != NULL && GDK_WINDOW_DESTROYED (leader)))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -4801,8 +4564,10 @@ gdk_window_set_decorations (GdkWindow      *window,
                            GdkWMDecoration decorations)
 {
   MotifWmHints hints;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
   
   /* initialize to zero to avoid writing uninitialized data to socket */
   memset(&hints, 0, sizeof(hints));
@@ -4827,8 +4592,10 @@ gdk_window_get_decorations(GdkWindow       *window,
   MotifWmHints *hints;
   gboolean result = FALSE;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return FALSE;
+  
   hints = gdk_window_get_mwm_hints (window);
   
   if (hints)
@@ -4873,6 +4640,10 @@ gdk_window_set_functions (GdkWindow    *window,
   MotifWmHints hints;
   
   g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
   
   /* initialize to zero to avoid writing uninitialized data to socket */
   memset(&hints, 0, sizeof(hints));
@@ -5917,9 +5688,8 @@ gdk_window_begin_resize_drag (GdkWindow     *window,
                               gint           root_y,
                               guint32        timestamp)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
@@ -5952,9 +5722,8 @@ gdk_window_begin_move_drag (GdkWindow *window,
                             gint       root_y,
                             guint32    timestamp)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
@@ -5988,7 +5757,8 @@ gdk_window_enable_synchronized_configure (GdkWindow *window)
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowImplX11 *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return;
 
   impl = GDK_WINDOW_IMPL_X11 (private->impl);
          
@@ -6019,7 +5789,8 @@ gdk_window_configure_finished (GdkWindow *window)
 {
   GdkWindowImplX11 *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return;
   
   impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
   if (!impl->use_synchronized_configure)
@@ -6060,6 +5831,11 @@ gdk_window_beep (GdkWindow *window)
 {
   GdkDisplay *display;
 
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  
   display = GDK_WINDOW_DISPLAY (window);
 
 #ifdef HAVE_XKB
@@ -6101,7 +5877,8 @@ gdk_window_set_opacity (GdkWindow *window,
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -6171,8 +5948,6 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->raise = gdk_window_x11_raise;
   iface->lower = gdk_window_x11_lower;
   iface->move_resize = gdk_window_x11_move_resize;
-  iface->scroll = _gdk_x11_window_scroll;
-  iface->move_region = _gdk_x11_window_move_region;
   iface->set_background = gdk_window_x11_set_background;
   iface->set_back_pixmap = gdk_window_x11_set_back_pixmap;
   iface->reparent = gdk_window_x11_reparent;
@@ -6184,7 +5959,7 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->set_child_shapes = gdk_window_x11_set_child_shapes;
   iface->merge_child_shapes = gdk_window_x11_merge_child_shapes;
   iface->set_static_gravities = gdk_window_x11_set_static_gravities;
-  iface->get_offsets = _gdk_x11_window_get_offsets;
+  iface->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
 }
 
 #define __GDK_WINDOW_X11_C__
index 2a2799b0799f334edad344da72277758d5176ccf..78c22aacc5206fcc70d9323fc18017b3d70212b6 100644 (file)
@@ -44,22 +44,6 @@ typedef struct _GdkWindowImplX11 GdkWindowImplX11;
 typedef struct _GdkWindowImplX11Class GdkWindowImplX11Class;
 typedef struct _GdkXPositionInfo GdkXPositionInfo;
 
-struct _GdkXPositionInfo
-{
-  gint x;
-  gint y;
-  gint width;
-  gint height;
-  gint x_offset;               /* Offsets to add to X coordinates within window */
-  gint y_offset;               /*   to get GDK coodinates within window */
-  guint big : 1;
-  guint mapped : 1;
-  guint no_bg : 1;             /* Set when the window background is temporarily
-                                * unset during resizing and scaling */
-  GdkRectangle clip_rect;      /* visible rectangle of window */
-};
-
-
 /* Window implementation for X11
  */
 
@@ -74,10 +58,8 @@ struct _GdkWindowImplX11
 {
   GdkDrawableImplX11 parent_instance;
 
-  gint width;
-  gint height;
-  
-  GdkXPositionInfo position_info;
+  guint no_bg : 1;             /* Set when the window background is temporarily
+                                * unset during resizing and scaling */
   GdkToplevelX11 *toplevel;    /* Toplevel-specific information */
   GdkCursor *cursor;
   gint8 toplevel_window_type;